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