我的疑惑开始于这篇文章,它说 C 语言中的 inline 函数是 static linkage,而 C++ 中的 inline 函数则是 external linkage。我第一次知道,原来 C 和 C++ 中的 inline 有如此的不同。于是,我尝试了这篇文章中的一个小实验。
有下面两个源文件:
// A.c
#include <stdio.h>
inline int foo() { return 3; }
void g() {
// 调用 foo() 并查看 foo() 函数的地址
printf("foo called from g: return value = %d, address = %p\n", foo(), &foo);
}// B.c
#include <stdio.h>
inline int foo() { return 3; }
void g();
int main() {
// 调用 foo() 并查看 foo() 函数的地址
printf("foo called from main: return value = %d, address = %p\n", foo(), &foo);
// 再调用 g(),让 g() 去调用 foo()
g();
}把这两个文件用 gcc 编译:
$ gcc A.c B.c链接时会报错:
Undefined symbols for architecture arm64:
"_foo", referenced from:
_g in A-0eb9b0.o
_main in B-95b4fd.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
也就是 B.c 里,说函数 foo() 找不到!但 foo() 明明就定义在 B.c 里,这里我十分不理解。
但如果用 g++ 编译(按 C++ 的方式编译这两个 C 文件):
$ g++ A.c B.c
就可以正常编译。运行结果:
❯ ./a.out
foo called from main: return value = 3, address = 0x104f23ed4
foo called from g: return value = 3, address = 0x104f23ed4
发现两边调用的 foo() 的地址相同,说明调用的是同一个 foo()。这也应证了 C++ 中的 inline 函数是 external linkage,所有翻译单元使用的都是同一个 foo() 函数。
如果想让 gcc 正常编译,需要给 inline 前面再加一个 static,编译后运行:
❯ ./a.out
foo called from main: return value = 3, address = 0x104bdff28
foo called from g: return value = 3, address = 0x104bdfed4
此时两边调用的 foo() 地址不一样,说明编译器生成了两个 foo() 函数。这是当然,因为 static 使得这个函数变成翻译单元独有的。
我疑惑的点,就在于,为什么用 gcc 的时候,不加 static 就不能编译?
找到一个类似的问题,有点看不懂,先放这,明天再看看:https://stackoverflow.com/questions/6312597/is-inline-without-static-or-extern-ever-useful-in-c99