我试图在线搜索一个好的答案,但没有得到一个我完全可以理解的答案.假设我有一个标题"add.h":
inline int add(int a, int b){ return a+b; }
一个名为"adddouble.c"的文件:
#include "add.h" int adddouble(int a, int b){ return 2*add(a,b); }
一个名为"addsquare.c"的文件:
#include "add.h" int addsquare(int a, int b){ return add(a,b)*add(a,b); }
主文件"main.c":
#includeint adddouble(int, int); int addsquare(int, int); int main(){ printf("add double = %d\n", adddouble(10,20)); printf("add square = %d\n", addsquare(10,20)); return 0; }
我使用gcc5.2.0来编译这些文件,但得到了:"架构x86_64的未定义符号:".如果我在add.h中添加静态到内联函数或添加声明"extern int add(int,int);" 到"adddouble.c",它成功编译没有错误.我是新的内联函数,我不知道如何解释和理解这种行为.谢谢
根据 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf,看起来内联函数在C和C++中的行为有所不同:
具有内部链接的任何函数都可以是内联函数.对于具有外部链接的函数,以下限制适用:如果使用内联函数说明符声明函数,则它也应在同一转换单元中定义.如果转换单元中函数的所有文件范围声明都包含不带extern的内联函数说明符,则该转换单元中的定义是内联定义.内联定义不提供函数的外部定义,也不禁止另一个转换单元中的外部定义.内联定义提供了外部定义的替代,翻译器可以使用该定义在同一翻译单元中实现对该功能的任何调用.未指定对函数的调用是使用内联定义还是使用外部定义.140)
如果你没有放在static
那里,你就是在没有实例化外部定义的情况下用外部链接定义内联函数.
extern int add(int, int);
实例化该函数的外部定义,并且您需要完成一次(在哪个文件中无关紧要)才能使链接成功(或者您可以标记内联函数static
并且问题消失).
(在C++中,在每个转换单元中inline
创建弱外部定义,因此您不必担心标记内容static
或实例化内联函数的一个外部定义 - g ++应该直接编译它而for f in *.c; do g++ -c "$f"; done; g++ *.o
没有任何问题.)