9

简单的问题:

给定以下程序:

#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,我不认为,根据我读过的内容:
链接器错误内联函数(因为这是在不同的对象中,并且处理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
4

3 回答 3

11

第 6.7.4 节第 7 段说:

任何具有内部链接的函数都可以是内联函数。对于具有外部链接的函数,适用以下限制: 如果函数用inline函数说明符声明,则它也应在同一翻译单元中定义。如果翻译单元中函数的所有文件范围声明都包含inline函数说明符 without extern,则该翻译单元中的定义是内联定义内联定义不提供函数的外部定义,也不禁止在另一个翻译单元中进行外部定义。内联定义提供了外部定义的替代方案,翻译器可以使用它来实现对同一翻译单元中函数的任何调用。未指定对函数的调用是使用内联定义还是外部定义

您的文件不包含 的外部定义addEmUp,并且编译器选择在调用中使用外部定义main

提供外部定义,或将其声明为static inline.

于 2013-05-24T17:54:08.343 回答
2

尝试在编译器命令中添加“-O”选项。仅当启用优化时才启用内联。

于 2013-05-24T17:45:11.253 回答
0

由于 6.9/5,该程序会导致未定义的行为(无需诊断),有时非正式地称为“一个定义规则”:

如果用外部链接声明的标识符在表达式中使用(而不是作为 sizeof 或 _Alignof 运算符的操作数的一部分,其结果是整数常量),则在整个程序的某处,该标识符应该只有一个外部定义;否则,不得超过一个。

您的程序使用标识符addEmUp,但没有为其提供外部定义。(如前所述,“内联定义不提供函数的外部定义”)。

我们不需要开始讨论函数调用调用的定义等等。 ODR 违规未定义且无需诊断的原因是为了让编译器编写者更容易;如果此代码需要诊断,那么编译器将不得不通过禁用内联优化来检查外部定义的存在,这确实是浪费时间。

于 2020-08-28T14:22:09.637 回答