两个 c 文件之间的全局内联函数

global inline function between two c files

之前问过。我想知道如何在全局范围内定义 inline 函数。

我想在test.h中声明inline函数,在main.c中定义从 test.c.

调用

main.c 和 test.c 都是 #include "test.h"(代码示例请点击上面的 link)。

这基本上是用户可以使用的某种回调函数 enable/disable。并且只有一个文件应该具有函数 defined.

我知道 inline 只是对编译器的一个建议,它对现代 CPU 没有太大影响,但这是针对 8 位微控制器的,确实需要它。

编辑:

我在 test.c 中有一个调用此内联函数的函数。我只想用 main.c 中定义的函数体替换调用。我希望这是有道理的。

假设您是认真的,所讨论的函数是回调,您不能内联回调。这没有意义,回调调用通常通过函数指针发生,我认为你不能指望编译器证明它的值是常量(并且在编译时已知)以便它可以替换调用使用内联代码。

它的工作方式就是这样,你将只有一个函数定义,假设它是函数 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

链接器将负责查找函数定义。

如果函数未在任何编译文件中定义,则

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

如果函数 returns void 那么一个不错的技巧是使用这个

#define inlinedFunction(parameters) \
    do {                            \
        /* function body here */    \
    } while (0)

您应该在宏定义的每一行末尾添加一个连续的反斜杠。

大多数 8 位微控制器代码是用类似于 C89 的语言编写的(通常有扩展,例如内联汇编),并且 inline 不是 官方 的一部分C 到 C99。所以首先要确定你正在编译的标准(如果有的话),如果 inline 是一个扩展(即不是 C99 内联),请查阅你的编译器手册。在该编程领域,编译器手册优先于 C 标准。

Per C99 如果 main.ctest.c 都需要调用同一个函数并且需要标记为 inline,那么我认为必须定义它在 header 中,因为 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?

但是,这可能会导致生成的 object 代码出现各种奇怪的行为。例如,我见过来自 major MCU mfg 的编译器(他们会故意不命名)为 inline 函数生成 object 代码 #included在给定的翻译单元中 而不是内联它们 。该文件包含在几个地方并包含许多功能,因此这导致整个代码库中整体 ROM 使用量大幅增加,因为链接器也无法删除死代码(请参阅 --gc-sections for gcc)和未能提高性能,因为这些函数从未真正内联,即使 技术上 内联的正确使用。

我们对这个特定问题的解决方案是将所有函数转换为宏(这提供了 inline 预期的性能优势),但另一种方法是从声明中删除 inline并将定义移动到单个 .c 文件。

TL;DR: 如果对 MCU 使用 inline,1) 查阅您的编译器手册,以及 2) 留意生成的 object 代码.

您可以在 C 中使用 inline 关键字,但如果您使用的是 GNU GCC 编译器,则内联函数也需要是 static 函数。因此,您只能在同一个源文件上使用这些函数。如果你想声明一个你在某个头文件中定义的全局内联函数,并在包含该头文件的源文件上使用它,你可以使用 GNU GCC 的 always_inline 属性,如下所示:

static inline __attribute__((always_inline)) int foo(int a)
{
  return a+2;
}

不要忘记在同一头文件中声明内联函数的主体。