1

根据我之前提出的这个问题。我想知道如何inline在全局范围内定义一个函数。

我想在 test.h 中声明 inline函数,在 main.c中定义它并从 test.c中调用它。

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

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

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

编辑:

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

4

4 回答 4

2

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

于 2015-02-19T12:59:07.140 回答
2

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

PerC99如果两者main.ctest.c需要调用同一个函数并且它需要被标记inline,那么我相信它必须在标题中定义,因为inline函数不能跨越翻译单元(即“.c”文件)。

例如:

测试.h:

static inline int add(int a, int b) { return a + b; }

主.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;
}

编辑:inline有关 C99用法的更好解释,请参见此处:如何在 C99 多文件项目中声明内联函数?

但是,这可能会导致生成的目标代码出现各种奇怪的行为。例如,我已经看到来自主要MCU 制造商(有意匿名)的编译器为给定翻译单元中的inline函数生成目标代码,而不是内联它们。该文件包含在多个位置并包含许多函数,因此这导致整个代码库中的整体 ROM 使用量大幅增加,因为链接器也无法删除死代码(请参阅参考资料)并且未能提高性能,因为这些函数实际上从未内联,即使它在技术上是正确使用内联。 #included--gc-sectionsgcc

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

TL;DR:如果inline用于 MCU,1) 请查阅您的编译器手册,以及 2) 密切关注生成的目标代码。

于 2015-02-19T13:15:19.703 回答
0

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

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

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

于 2019-03-25T13:50:07.733 回答
-1

它的工作方式就是这样,你将只有一个函数的定义,说它是函数int add(int x, int y);然后你定义它main.c

主.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);
}

将替换add(x, y)x + y.

如果函数返回void,那么一个不错的技巧就是使用它

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

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

于 2015-02-19T12:59:18.797 回答