gcc和g++的区别以及extern "C"的作用
来源:互联网 发布:收徒网源码带后台 编辑:程序博客网 时间:2024/05/09 02:57
首先来写一个简单的c代码~
//externC_funA.c void funA() {}
利用gcc进行编译生成汇编:
gcc -c externC_funA.c -S
得到的汇编代码如下:
.file "externC_funA.c" .text .globl funA //注意这里的标示符为funA .type funA, @function funA: pushl %ebp movl %esp, %ebp popl %ebp ret .size funA, .-funA .ident "GCC: (GNU) 4.3.0 20080428 (Red Hat 4.3.0-8)" .section .note.GNU-stack,"",@progbits
同样的,我们将该文件改为cpp后缀,重新编译
//externC_funA.cpp void funA() {}
gcc -c externC_funA.cpp -S
g++ -c externC_funA.cpp -S
按照上面两种方法编译,得到的汇编代码一样
.file "externC_funA.cpp" .text .globl _Z4funAv//注意这里的标示符为_Z4funAv,不同形参版本的funA生成的标示符会不一样! .type _Z4funAv, @function _Z4funAv: .LFB2: pushl %ebp .LCFI0: movl %esp, %ebp .LCFI1: popl %ebp ret .LFE2: .size _Z4funAv, .-_Z4funAv .ident "GCC: (GNU) 4.3.0 20080428 (Red Hat 4.3.0-8)" .section .note.GNU-stack,"",@progbits
第三个例子:
//externC_funA.cpp1 void funA(){}void funA(int a){}
得到的汇编如下:
.file "externC_funA.cpp" .text .globl _Z4funAv//funA()对应的标示符,最后那个v表示void形参 .type _Z4funAv, @function _Z4funAv: .LFB2: pushl %ebp .LCFI0: movl %esp, %ebp .LCFI1: popl %ebp ret .LFE2: .size _Z4funAv, .-_Z4funAv .globl _Z4funAi//funA(int)对应的标示符,最后那个i表示int形参 .type _Z4funAi, @function _Z4funAi: .LFB3: pushl %ebp .LCFI2: movl %esp, %ebp .LCFI3: popl %ebp ret .LFE3: .size _Z4funAi, .-_Z4funAi .ident "GCC: (GNU) 4.3.0 20080428 (Red Hat 4.3.0-8)" .section .note.GNU-stack,"",@progbits
从上面的两个对比,我们可以得到下面几个结论:
1.gcc会自动识别文件的后缀名,对于.c文件,gcc按照c语言的方式进行编译;而对于.cxx文件,gcc按照c++语言的方式进行编译。
2.c++能够实现重载的原因是,编译器对不同形参版本的函数,生成的标示符会不同。
3.对于cxx文件,在编译阶段,g++和gcc是等价的。
那么g++跟gcc又有什么区别呢,主要的区别是在链接阶段。
//externC_funA.cppvoid funA(){}//externC.cppextern void funA();int main(){ funA(); //按照此种方法,生成的汇编为 call _Z4funAv
gcc -c externC_funA.cpp // .globl _Z4funAvgcc -c externC.cpp // call _Z4funAvgcc -o externC externC.o externC_funA.o //undefined reference to `__gxx_personality_v0'
按道理生成的标示符是_Z4funAv,调用的也是_Z4funAv,应该没错啊,为什么在链接的时候出错了呢?主要是最后一步用的是gcc来进行链接,而显然gcc不支持c++方式的链接,所以会报错。如果改成以下就不会出现问题了。
g++ -o externC externC.o externC_funA.o
继续试验!!!
将externC_funA.cpp改成externC_funA.c
//externC_funA.cvoid funA(){}//externC.cppextern void funA();int main(){ funA();}
gcc -c externC_funA.c //.globl funAgcc -c externC.cpp.globl funA //call_Z4funAvg++ -o externC externC.o externC_funA.o //undefined reference to `funA()'
出现上面这个错误是明显的,因为两个标示符根本就不一样,就算用了g++也是不起作用的~~所以此时extern "C"就可以发挥作用了。
//externC_funA.cvoid funA(){}//externC.cppextern "C"{extern void funA();}int main(){ funA();//通过加入extern “C”,此处生成的汇编为 call funA}
gcc -c externC_funA.c gcc -c externC.cppg++ -o externC externC.o externC_funA.o
到这里,也不用我来总结了,extern “C”的作用一目了然~按照c语言的方式生成汇编,以免造成链接错误。extern "C"主要的应用就在于一个c的链接库已经生成好,不想再修改了,或者说这个链接库是别人写的,不知道源代码,根本就没法修改。在这种情况下,我们用C++调用库中的函数就能够正确链接了。
- gcc和g++的区别以及extern "C"的作用
- gcc和g++的区别__C++中的extern C""
- gcc和g++的区别__C++中的extern C""
- c和c++的区别&gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- gcc和g++的区别
- VB作业之计算圆的面积
- IDC_HAND 未声明的标识符
- mysql的安装配置
- oracle中rownum与rowid使用方法
- SURVIVING THE TOP TEN CHALLENGES OF SOFTWARE TESTING: A PEOPLE-ORIENTED APPROACH
- gcc和g++的区别以及extern "C"的作用
- 添加强名称
- 用rsync,crontab实现Linux服务器间的定时备份
- C++ 类静态成员变量存取出错 undefined reference to 'xxx'
- 程序员笔试题----2012腾讯实习生笔试题
- 教你如何迅速秒杀掉:99%的海量数据处理面试题 .
- 大学毕业后拉开差距的真正原因
- C#多线程——Timer
- VB作业之素数