C语言inline函数外部定义与翻译单元相关技术疑问
关于C语言inline函数与翻译单元的疑问解答
1. 什么是“另一个翻译单元”?
C语言里的翻译单元(TU),就是单个.c源文件加上它预处理后展开的所有头文件内容——每个翻译单元会被单独编译成.o目标文件,最后由链接器把多个目标文件合并成可执行程序。
“在另一个翻译单元中”的意思是:如果你的inline函数是外部链接(默认不带static的inline函数都是外部链接),并且代码里引用了它,那你必须在另一个独立的.c文件里提供这个函数的普通(非inline)定义,这个定义就是所谓的“外部定义”。
2. 第一个测试代码的错误原因
看这段代码:
inline int foo() { return 0; } int main(void) { return foo(); }
按照C标准,不带static的inline函数默认是外部链接,但这个inline定义本身不算“外部定义”——它只是给编译器提供的一个内联替换候选,不会生成全局可见的函数实体。当编译器没有选择内联foo()时,链接阶段就会去寻找foo的外部定义,但你完全没提供,所以链接器就会报“undefined reference to foo”的错误。
3. 添加同一TU的外部声明后错误消失的原因
修改后的代码:
int foo(); inline int foo() { return 0; } int main(void) { return foo(); }
这里的int foo();是一个外部声明,它明确告诉编译器:foo是一个具有外部链接的函数。而下面的inline定义,在有这个外部声明的前提下,GCC等编译器会把这个inline定义同时当作外部定义来处理(这是编译器的扩展特性,并非C标准强制要求),所以链接时能找到foo的实体,错误自然就消失了。
4. 是否必须在同一文件中添加外部声明?
不是必须的。标准合规的做法是:
- 在头文件中同时写
inline函数定义和外部声明,比如:
所有需要使用extern int foo(); inline int foo() { return 0; }foo的源文件都包含这个头文件; - 然后在某一个单独的
.c文件(比如foo.c)里写foo的普通外部定义:int foo() { return 0; }
当然,像GCC这类编译器支持扩展特性:如果同一个TU里既有inline定义又有外部声明,会自动把inline定义当作外部定义使用,这样就不需要额外的TU了,但这属于编译器的非标准行为。
内容的提问来源于stack exchange,提问作者k1r1t0
相关产品推荐
相关产品推荐

