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

问题描述 投票:1回答:4

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

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

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

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

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

编辑:

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

c global inline-functions
4个回答
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)

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


2
投票

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


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 for gcc)并且无法提高性能,因为函数是从来没有实际内联,即使它在技术上是正确使用内联。

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

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


0
投票

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.