之后我问this question。我想知道如何在全局范围内定义inline
函数。
我想在test.h中声明 inline
函数,在main.c中定义,在调用来测试它.C。
main.c和test.c #include "test.h"
(代码示例请点击上面的链接)。
这基本上是某种用户可以启用/禁用的回调函数。只有一个文件应该具有定义功能。
我知道inline
只是对编译器的一个建议,它在现代CPU上没有太大区别,但这适用于8位微控制器而且确实需要它。
修改
我在test.c中有一个函数,它调用这个内联函数。我只想用main.c中定义的函数体替换调用。我希望这是有道理的。
答案 0 :(得分:2)
假设你的意思是你所说的,所讨论的功能是一个回调,你就不能内联一个回调。它没有意义,回调调用通常通过函数指针发生,我不认为你可以期望编译器证明它的值是常量的(并且在编译时已知),以便它可以使用内联代码替换调用。
答案 1 :(得分:2)
大多数8位微控制器代码是用近似于C89的语言编写的(通常有扩展,例如内联汇编),而inline
在C99之前不是正式 C的一部分。因此,首先要确定您正在编译的标准(如果有的话),如果inline
是扩展名(即不是C99内联),请查阅编译器手册。编程手册在编程领域优先于C标准。
每C99
如果main.c
和test.c
都需要调用相同的函数并且需要将其标记为inline
,那么我相信它必须在标题,因为inline
函数不能跨越翻译单元(即" .c"文件)。
例如:
<强> test.h:强>
static inline int add(int a, int b) { return a + b; }
<强> main.c中:强>
#include "test.h"
void main(void)
{
int x = add(10,15);
}
<强> test.c的:强>
#include "test.h"
int test(void)
{
int x = add(10,15);
return x;
}
编辑:有关C99 inline
用法的更好说明,请参阅此处:How to declare an inline function in C99 multi-file project?
但是,这会导致生成的对象代码出现各种奇怪的行为。例如,我已经看到来自主 MCU制造商(有意无人命名)的编译器在给定的翻译单元中为inline
函数#included
生成对象代码而不是内联。该文件包含在多个地方并包含许多功能,因此导致整个代码库中整体ROM使用量大幅增加,因为链接器也无法删除死代码(请参阅--gc-sections
gcc
)AND未能提高性能,因为函数从未实际内联,即使它技术上正确使用内联。
我们对这一特定问题的解决方案是将所有函数转换为宏(这使得inline
具有性能优势),但另一种方法是从声明中移除inline
并移动定义为单个.c
文件。
TL; DR:如果对MCU使用inline
,1)请参阅编译器手册,2)密切关注生成的目标代码。
答案 2 :(得分:0)
它的工作方式就是这样,你只有一个函数定义,比如函数int add(int x, int y);
然后你在main.c
中定义它
<强>的main.c 强>:
int add(int x, int y)
{
return x + y;
}
然后如果你想在另一个c文件中使用它,你只需要这个
<强> test.c的强>
int add(int x, int y); /* just a declaration, a function prototype */
int addWrapper(int x, int y)
{
return add(x, y);
}
像这样编译
gcc -Wall -Werror main.c test.c -o some_output_file_name
并且链接器将负责查找函数定义。
如果在任何编译文件中没有定义该函数,那么a
Undefined reference to `int add(int x, int y);' in ...
将发出错误。
如果要强制编译器插入函数体,则自己插入函数体,使用预处理器宏
<强> header.h 强>
#define add(x,y) ((x) + (y))
然后
#include "header.h"
int addWrapper(int x, int y)
{
return add(x, y);
}
将add(x, y)
替换为x + y
。
如果函数返回void
,那么一个很好的技巧就是使用这个
#define inlinedFunction(parameters) \
do { \
/* function body here */ \
} while (0)
你应该在宏定义的每一行的末尾添加一个连续反斜杠。
答案 3 :(得分:0)
您可以在C语言中使用inline
关键字,但是如果您使用的是GNU GCC编译器,它将要求内联函数也必须是static
函数。因此,您只能在同一个源文件上使用这些功能。如果要声明在某些头文件中定义的全局内联函数,并在包含该头文件的源文件中使用它,则可以使用GNU GCC的always_inline
属性,如下所示:
static inline __attribute__((always_inline)) int foo(int a)
{
return a+2;
}
别忘了在同一头文件中声明内联函数的主体。