浅析extern “C”的作用
2015-09-13 20:58
387 查看
浅析extern “C”的作用
关于extern “C”的作用和意思,网上资料已经有很多了(我也参考了几篇),不过我还是觉得有必要自己总结一下,毕竟“好记性不如烂笔头”嘛~~
到C标准函数库的头文件里看看,一般会经常看见有如下宏定义(除非你从来没有查看类似printf函数在头文件中的定义,就另当别论了:-()
简单来说,这个extern“C”用于C++代码调用C的函数(至于C代码如何调用C++函数,还是问问Google大神吧~)
先撇开上述的extern “C”,看看C函数和C++函数的汇编代码,就知道在目标文件中,C函数名和C++函数名采用不同的命名规则。
VS2010新建一个Windows Console工程,添加一个.c和.cpp文件,文件里的代码都一样,如下
为了使汇编文件的内容简单一些,这里函数体是空,而且没有引入任何头文件。VS2010默认不输出.asm文件,即汇编文件。在工程的配置中,让VS2010输出汇编文件,如下
编译解决方案(或按“F7”),可以在工程目录的Debug文件夹下,找到对应的两个汇编文件,内容如下
没有必要把这里全部的汇编代码看懂,只要明白在源代码中同一个hello函数,在翻译过来的.asm文件中,hello函数名的命名不一样就行了。
很明显,如果C++代码要调用C函数,需要按照C函数编译后的函数名去调用这个函数。所以,extern “C”的作用就是告诉编译器,花括号“{}”中间的这些函数声明全部都是C函数。
下面修改一下.c和.cpp文件的内容,如下
这里要说明下,由于.c和.cpp文件在同一个工程下,所以简单起见,没有使用头文件引入hello函数,这里hello函数是全局的。运行工程发现出错如下
这里?hello@@YAXXZ就是上面.cpp文件中hello函数编译后出现在对应的.asm文件中的。显然,编译器按照这个名称去找目标文件(.obj文件)中的hello是找不到的,因为.c文件编译后的.obj文件中,hello函数名被改成_hello。
这时,把extern “C”加到.cpp文件中,如下
果然,程序可以通过编译运行了。到这里,基本上extern ”C”的作用都讲清楚了。至于__cplusplus宏,用于判断当前源文件是不是C++源文件,因为extern “C”这种写法在C源文件中不允许的,如下,所以使用__cplusplus宏可以避免extern “C”被引入到C源文件中。即
(1)当前源文件是C++,则__cplusplus宏生效,extern “C”以及花括号“{}”的内容被引入C++源代码中;
(2)当前源文件是C,则__cplusplus宏无效,extern “C”以及花括号“{}”的内容不被引入C源代码中。
参考资料:
1、http://tech.163.com/06/0118/09/27O66HCC0009159Q.html
2、http://hi.baidu.com/mailrabbit/item/d53990f26265111aa7298876
3、/article/1457614.html
4、http://luleimi.blog.163.com/blog/static/175219645201281244439794/
转自:/article/8363586.html
关于extern “C”的作用和意思,网上资料已经有很多了(我也参考了几篇),不过我还是觉得有必要自己总结一下,毕竟“好记性不如烂笔头”嘛~~
到C标准函数库的头文件里看看,一般会经常看见有如下宏定义(除非你从来没有查看类似printf函数在头文件中的定义,就另当别论了:-()
#ifdef __cplusplus extern "C" { #endif …… (C函数声明) #ifdef __cplusplus } #endif
简单来说,这个extern“C”用于C++代码调用C的函数(至于C代码如何调用C++函数,还是问问Google大神吧~)
先撇开上述的extern “C”,看看C函数和C++函数的汇编代码,就知道在目标文件中,C函数名和C++函数名采用不同的命名规则。
VS2010新建一个Windows Console工程,添加一个.c和.cpp文件,文件里的代码都一样,如下
void hello() { }
为了使汇编文件的内容简单一些,这里函数体是空,而且没有引入任何头文件。VS2010默认不输出.asm文件,即汇编文件。在工程的配置中,让VS2010输出汇编文件,如下
编译解决方案(或按“F7”),可以在工程目录的Debug文件夹下,找到对应的两个汇编文件,内容如下
没有必要把这里全部的汇编代码看懂,只要明白在源代码中同一个hello函数,在翻译过来的.asm文件中,hello函数名的命名不一样就行了。
很明显,如果C++代码要调用C函数,需要按照C函数编译后的函数名去调用这个函数。所以,extern “C”的作用就是告诉编译器,花括号“{}”中间的这些函数声明全部都是C函数。
下面修改一下.c和.cpp文件的内容,如下
// C代码 #include <stdio.h> void hello() { printf("Hello, world!\n"); }
// C++代码 void hello(); int main(void) { hello(); }
这里要说明下,由于.c和.cpp文件在同一个工程下,所以简单起见,没有使用头文件引入hello函数,这里hello函数是全局的。运行工程发现出错如下
这里?hello@@YAXXZ就是上面.cpp文件中hello函数编译后出现在对应的.asm文件中的。显然,编译器按照这个名称去找目标文件(.obj文件)中的hello是找不到的,因为.c文件编译后的.obj文件中,hello函数名被改成_hello。
这时,把extern “C”加到.cpp文件中,如下
extern "C" { void hello(); }; int main(void) { hello(); }
果然,程序可以通过编译运行了。到这里,基本上extern ”C”的作用都讲清楚了。至于__cplusplus宏,用于判断当前源文件是不是C++源文件,因为extern “C”这种写法在C源文件中不允许的,如下,所以使用__cplusplus宏可以避免extern “C”被引入到C源文件中。即
(1)当前源文件是C++,则__cplusplus宏生效,extern “C”以及花括号“{}”的内容被引入C++源代码中;
(2)当前源文件是C,则__cplusplus宏无效,extern “C”以及花括号“{}”的内容不被引入C源代码中。
参考资料:
1、http://tech.163.com/06/0118/09/27O66HCC0009159Q.html
2、http://hi.baidu.com/mailrabbit/item/d53990f26265111aa7298876
3、/article/1457614.html
4、http://luleimi.blog.163.com/blog/static/175219645201281244439794/
转自:/article/8363586.html
相关文章推荐
- 杭州电子科技大学acm--2017
- 移动端的click
- 拉普拉斯矩阵/映射/聚类
- JS基本语法
- IT男的工作现状
- 欢迎使用CSDN-markdown编辑器
- Java中抽象类和接口的区别
- extern C的作用详解
- 想考个数据库工程师证要做哪些
- php使用php include之后页首有空白
- Service与Activity与交流AIDL
- window
- poj1284 Primitive Roots
- HDU 1856 More is better(求最大秩的集合 )
- 【收集】cocos2dx中加载使用plist文件
- 文章标题
- [logstash-input-file]插件使用详解
- 2.3 ARM寄存器详解
- 二分
- linux运维实战练习-2015年9月13日-9月15日课程作业(练习)安排