4.
5. U __gxx_personality_v0
6.
7. 0000000000000028 T elipse_area
8.
9. 0000000000000052 T main
10.
11. 0000000000000000 T rect_area
可见,使用extern “C”关键字之后,符号按照C语言的格式来组织了。
事实上,C标准库中使用了大量的extern “C”关键字,因为C标准库也是可以用C++编译器编译的,但是要确保编译之后仍然保持C的接口而不是C++的接口(因为是C标准库),所以需要使用extern “C”关键字。
下面是一个简单的例子:
1. /*
2. * libc_test.c
3. * a demo program to show that how the standard C
4.
5. * library are compiled when encountering a C++ compiler
6.
7. */
8. #include
9. int main(int argc,char * argv[])
10.
11. {
12. puts("hello world.\n");
13. return 0;
14. }
搜索一下puts,我们并没有看到extern “C”.奇怪么?
1. [lichao@sg01 name_mangling]$ g++ -E libc_test.c | grep 'puts'
2.
3. extern int fputs (__const char *__restrict __s, FILE *__restrict __stream);
4.
5. extern int puts (__const char *__s);
6.
7. extern int fputs_unlocked (__const char *__restrict __s,
8.
9. puts("hello world.\n");
搜索一下 extern “C”试下
1. [lichao@sg01 name_mangling]$ g++ -E libc_test.c | grep 'extern "C"'
2.
3. extern "C" {
4.
5. extern "C" {
标准
不同编译器使用不同的方式进行name mangling, 你可能会问为什么不将C++的 name mangling标准化,这样就能实现各个编译器之间的互操作了。事实上,在C++的FAQ列表上有对此问题的回答:
"Compilers differ as to how objects are laid out, how multiple inheritance is implemented, how virtual function calls are handled, and so on, so if the name mangling were made the same, your programs would link against libraries provided from other compilers but then crash when run. For this reason, the ARM (Annotated C++ Reference Manual) encourages compiler writers to make their name mangling different from that of other compilers for the same platform. Incompatible libraries are then detected at link time, rather than at run time."
“编译器由于内部实现的不同而不同,内部实现包括对象在内存中的布局,继承的实现,虚函数调用处理等等。所以如果将name mangling标准化了,不错,你的程序确实能够链接成功,但是运行肯定要崩的。恰恰是因为这个原因,ARM鼓励为同一平台提供的不同编译器应该使用不同的name mangling方式。这样在编译的时候,不兼容的库就会被检测到,而不至于链接时虽然通过了,但是运行时崩溃了。”
显然,这是基于“运行时崩溃比链接时失败的代价更大”这个原则而考虑的。
GCC的name mangling
GCC采用IA 64的name mangling方案,此方案定义于Intel IA64 standard ABI.在g++的FAQ列表中有以下一段话:
"GNU C++ does not do name mangling in the same way as other C++ compilers.
This means that object files compiled with one compiler cannot be used with
another”
GNU C++的name mangling方案和其他C++编译器方案不同,所以一种编译器生成的目标文件并不能被另外一种编译器生成的目标文件使用。
以下为内置的编码类型:
1. Builtin types encoding
2.
3.
4. ::= w # wchar_t
5. ::= b # bool
6. ::= c # char
7. ::= a # signed char
8. ::= h # unsigned char
9. ::= s # short
10. ::= t # unsigned short
11. ::= i # int
12. ::= j # unsigned int
13. ::= l # long
14. ::= m # unsigned long
15. ::= x # long long, __int64
16. ::= y # unsigned long long, __int64
17. ::= n # __int128
18. ::= o # unsigned __int128
19. ::= f # float
20. ::= d # double
21. ::= e # long double, __float80
22. ::= g # __float128
23. ::= z # ellipsis
24. ::= u
操作符编码:
Operator encoding
1.
2. ::= na # new[]
3. ::= dl # delete