Skip to content

Instantly share code, notes, and snippets.

@ZJUGuoShuai
Created July 14, 2022 13:48
Show Gist options
  • Select an option

  • Save ZJUGuoShuai/31beabea33eef466733e9f81cf4c7df1 to your computer and use it in GitHub Desktop.

Select an option

Save ZJUGuoShuai/31beabea33eef466733e9f81cf4c7df1 to your computer and use it in GitHub Desktop.

对 C/C++ 中 inline 的疑惑

我的疑惑开始于这篇文章,它说 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 就不能编译?

@ZJUGuoShuai

Copy link
Copy Markdown
Author

找到一个类似的问题,有点看不懂,先放这,明天再看看:https://stackoverflow.com/questions/6312597/is-inline-without-static-or-extern-ever-useful-in-c99

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment