PL: name mangling and extern "C" in C++

主要参考:

  https://en.wikipedia.org/wiki/Name_mangling

  https://en.wikipedia.org/wiki/Talk%3AName_mangling

(我发现wikipedia的可读性真的很强啊,比百度百科强多了)

 

在编程语言中,有个术语叫 name mangling, 意思是编译器为一些 identifiers 增加一些修饰符号,使得一些含有歧义的 identifier 可以被区分开来。

比如,C++ 和 Java 中都允许function overload,所以会有很多重名的函数名称,这时候就需要使用name mangling, 为不同的同名函数增加一些修饰,使得在以后的使用中可以被区分开来。

又比如,C++中,处于不同的namespace的identifier是可以重名的,所以要用 name mangling 将不同namespace 的identifier区分开来。

又比如,Java 中可以有匿名类,但是匿名类也是需要名字的,否则后面就不能被使用了,这时候就需要name mangling.

 

但是,这些,对于对编译器技术不感兴趣的人来说有什么用呢?

 

其实,我这篇博文主要是想讲C++ 里面的  extern "C"  的:

  在C++程序中引用C的代码(比如C标准库里的函数)的时候,要加上  extern "C"  , 否则,在链接的时候很可能会出现错误。

  这是由于,C语言中是没有name mangling的,但是C++有。

  C编译器在编译的时候不会对identifier做name mangling,但是对于C++编译器,假如引用C代码但是却不加  extern "C" ,它就会把那个函数名改得面目全非(name mangling)。

  

  结果,用C++编译器编译的C程序的 函数名变量名等 与C库里的同名函数,变量对应不上(因为C++编译器对C程序做了name mangling,改了别人的名字),最后在链接的时候,很有可能会发生“ Unsolved References "这种错误。

  

  有人就问了,为什么在C++程序里使用C标准库里的函数,比如  printf() ,但是不使用 extern "C"  ,就没有发生链接时错误呢?

  原因是,其实在C++所使用的 stdio.h 头文件里,其实已经有了一个 extern "C" 。在 stdio.h 头文件里有一个 __BEGIN_DECLS 宏,这个宏在 sys/cdefs.h 里面被声明为 #define __BEGIN_DECLS extern "C" {

   (  cstdio 其实就仅仅include了 stdio.h ,什么都没干)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

:)

 

posted @ 2016-05-15 22:20  walkerlala  阅读(377)  评论(0编辑  收藏  举报