简单的问题:
给出以下程序:
#include <stdio.h>
inline void addEmUp(int a, int b, int * result)
{
if (result) {
*result = a+b;
}
}
int main(int argc, const char * argv[])
{
int i;
addEmUp(1, 2, &i);
return 0;
}
我收到链接器错误...
Undefined symbols for architecture x86_64:
_addEmUp", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
似乎没有费心去编译它。
根据我所读到的内容,它不应该是static
,我不会想到:
Linker error inline function(因为这是一个不同的对象,处理2个定义而不是零)
这是一个相关链接,但它是c ++,我不认为在标准C中将代码放在标题中是一种好习惯:
inline function linker error
编译信息:
cc --version
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix
编译示例:
# cc main.c
Undefined symbols for architecture x86_64:
"_addEmUp", referenced from:
_main in main-sq3kr4.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocatio
答案 0 :(得分:11)
第6.7.4节第7段说:
任何具有内部链接的函数都可以是内联函数。对于具有外部链接的函数,以下限制适用:如果使用
inline
函数说明符声明函数,则它也应在同一转换单元中定义。如果翻译单元中函数的所有文件范围声明都包含inline
函数说明符而没有extern
,那么该翻译单元中的定义是内联定义。 内联定义不提供函数的外部定义,并且不禁止其他翻译单元中的外部定义。内联定义提供了外部定义的替代,翻译器可以使用该定义在同一翻译单元中实现对该功能的任何调用。 未指定对函数的调用是使用内联定义还是使用外部定义。
您的文件不包含addEmUp
的外部定义,编译器选择在main
的调用中使用外部定义。
提供外部定义,或将其声明为static inline
。
答案 1 :(得分:3)
尝试添加&#34; -O&#34;编译器命令的选项。仅在启用优化时才会启用内联。
答案 2 :(得分:0)
由于6.9 / 5,该程序导致未定义的行为(无需诊断),有时被非正式地称为“一个定义规则”:
如果在表达式中使用了用外部链接声明的标识符(不是作为sizeof或_Alignof运算符的操作数的一部分,其结果是一个整数常量),则在整个程序中的某个地方应该有一个用于标识符;否则,最多只能有一个。
您的程序使用标识符addEmUp
,同时不为其提供外部定义。 (如前所述,“内联定义不为函数提供外部定义”。)
我们不必再讨论函数调用调用等等的定义。等等。无需诊断就可以定义ODR违例的原因是为了使编译器编写者更容易;如果此代码需要诊断,则编译器将不得不通过禁用内联优化的方式来检查是否存在外部定义,这确实是在浪费时间。