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

时间:2015-02-19 12:48:12

标签: c global inline-functions

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

我想在test.h中声明 inline函数,在main.c中定义,在调用来测试它.C。

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

这基本上是某种用户可以启用/禁用的回调函数。只有一个文件应该具有定义功能。

我知道inline只是对编译器的一个建议,它在现代CPU上没有太大区别,但这适用于8位微控制器而且确实需要它。

修改

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

4 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:2)

大多数8位微控制器代码是用近似于C89的语言编写的(通常有扩展,例如内联汇编),而inline在C99之前不是正式 C的一部分。因此,首先要确定您正在编译的标准(如果有的话),如果inline是扩展名(即不是C99内联),请查阅编译器手册。编程手册在编程领域优先于C标准。

C99如果main.ctest.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;
}

别忘了在同一头文件中声明内联函数的主体。