您的位置:首页 > 编程语言 > C语言/C++

gcc和g++的区别__C++中的extern C""

2017-07-27 10:18 405 查看
**********************************************************************
**********************************************************************
gcc和g++的区别
**********************************************************************
gcc/g++在执行编译工作的时候,总共需要4步 
  1.预处理,生成.i的文件[预处理器cpp] 
  2.将预处理后的文件转换成汇编语言,生成文件.s[编译器egcs] 
  3.由汇编变为目标代码(机器代码)生成.o的文件[汇编器as] 
  4.连接目标代码,生成可执行程序[链接器ld]
 When you invoke GCC, it normally does preprocessing, compilation, assembly and linking.  The 
       "overall options" allow you to stop this process at an intermediate stage.  For example, the 
       -c option says not to run the linker.  Then the output consists of object files output by 
       the assembler. 
       -E  Stop after the preprocessing stage; do not run the compiler proper.  The output is in 
           the form of preprocessed source code, which is sent to the standard output. 
       -S  Stop after the stage of compilation proper; do not assemble.  The output is in the form 
           of an assembler code file for each non-assembler input file specified. 
**********************************************************************
********************************************************************** 
1、g++把.c 和.cpp都当成c++程序来编译了,而gcc将.cpp当c++程序来编译。 
编译阶段,g++会调用gcc,对于c++代码,两者是等价的,但是因为gcc命令不能自动和C++程序使用的库联接,所以通常用g++来完成链接,为了统一起见,干脆编译/链接统统用g++了。 
示例: 
/********************************************************************** 
 * Compiler: gcc 4.5.1 20100924 (Red Hat 4.5.1-4) 
 * Last Update: Sun 27 May 2012 04:05:23 PM CST 
 * File Name: test.cpp 
 * Description: 
 ************************************************************************/ 
#include <iostream> 
int main() 

    std::cout<<"love"<<std::endl;    
    return 0; 

[test1@localhost tempCode]$ gcc -o test test.cpp 
/tmp/cczBzjdU.o: In function `main': 
test.cpp:(.text+0x14): undefined reference to `std::cout' 
collect2: ld returned 1 exit status 
[test1@localhost tempCode]$ g++ -o test test.cpp  用g++就能成功。
**********************************************************************
但如果要用gcc链接C++标准库的话,可以这样做
[test1@localhost tempCode]$ gcc -o test test.cpp -lstdc++ 
********************************************************************** 
2、__cplusplus这个宏标志着编译器将会把代码按C还是C++语法来解释。 
例如void foo(int x, int y); 
该函数被C编译器编译后在符号表中的名字为foo,而C++编译器则会产生像_Z3fooii之类的名字用来支持函数重载和类型安全连接。由于编译后在符号表中的名字不同,C++程序不能直接调用C函数。C++提供了一个C连接交换指定符号extern“C”来解决这个问题
**********************************************************************
**********************************************************************
**********************************************************************
C++中的extern C""
/**********************************************************************
* Compiler: gcc 4.5.1 20100924 (Red Hat 4.5.1-4)
* Last Update: Sun 27 May 2012 03:21:50 PM CST
* File Name: cExample.h
* Description: 
************************************************************************/
extern int funcTest(int a);
/**********************************************************************
* Compiler: gcc 4.5.1 20100924 (Red Hat 4.5.1-4)
* Last Update: Sun 27 May 2012 03:23:03 PM CST
* File Name: cExample.c
* Description: 
************************************************************************/
#include "cExample.h"
#include <stdio.h>
int funcTest(int x)
{
    printf("%d\n", x);
}
/**********************************************************************
* Compiler: gcc 4.5.1 20100924 (Red Hat 4.5.1-4)
* Last Update: Sun 27 May 2012 03:11:50 PM CST
* File Name: 1.cpp
* Description: 
************************************************************************/
//#include <stdio.h>
//#ifdef __cplusplus
//extern "C" 
//{
//#endif
#include "cExample.h"
//#ifdef __cplusplus
//}
//#endif
int main(int argc, char* argv[])
{
    funcTest(1);
    return 0;
}
下面用gcc的-S选项,只激活预处理和编译,把文件编译成为汇编代码。
[test1@localhost tempCode]$ gcc -S cExample.c 
[test1@localhost tempCode]$ gvim cExample..s 
.globl funcTest
.type funcTest, @function
funcTest:
查看汇编代码可以看到cExample.c 中的函数funcTest在符号表中的名字为 funcTest。
也可以用-c选项生成目标代码,直接查看目标代码在符号表中的名字。
 the   -c option says not to run the linker.  Then the output consists of object files output by  the assembler. 
[test1@localhost tempCode]$ gcc -c cExample.c      //生成目标文件
使用objdump - display information from object files. 
       -t  Print the symbol table entries of the file. 
[test1@localhost tempCode]$ objdump -t cExample.o
cExample.o:     file format elf32-i386 
SYMBOL TABLE: 
00000000 l    df *ABS* 00000000 cExample.c 
00000000 g     F .text 0000001c funcTest 
00000000         *UND* 00000000 printf 
[test1@localhost tempCode]$ g++ -o 1 1.cpp cExample.o 
/tmp/ccAodC5a.o: In function `main': 
1.cpp:(.text+0x11): undefined reference to `funcTest(int)' 
collect2: ld returned 1 exit status 
单独生成1.cpp的目标代码进行查看
[test1@localhost tempCode]$ g++ -c 1.cpp 
[test1@localhost tempCode]$ objdump -t 1.o 
1.o:     file format elf32-i386 
SYMBOL TABLE: 
00000000 l    df *ABS* 00000000 1.cpp 
00000000 g     F .text 0000001c main 
00000000         *UND* 00000000 _Z8funcTesti 
可看到funcTest在1.o符号表中的名字是_Z8funcTesti ,与funcTest在cExample.o符号表中的名字不同,故链接时失败了。
下面在1.cpp中加入extern “C”,这样子就告诉C++编译器将extern “C”{}所包括的东西按照C编译器去生成目标代码,这样子不会出现函数名在.cpp目标代码的符号表中的名字与.c目标代码中的名字不同。__cplusplus这个宏标志着编译器将会把代码按C还是C++语法来解释。
/**********************************************************************
* Compiler: gcc 4.5.1 20100924 (Red Hat 4.5.1-4)
* Last Update: Sun 27 May 2012 03:11:50 PM CST
* File Name: 1.cpp
* Description: 
************************************************************************/
#include <stdio.h>
#ifdef __cplusplus
extern "C" 
{
#endif
#include "cExample.h"
#ifdef __cplusplus
}
#endif
int main(int argc, char* argv[])
{
    funcTest(1);
    return 0;
}
[test1@localhost tempCode]$ g++ -c 1.cpp 
[test1@localhost tempCode]$ objdump -t 1.o 
1.o:     file format elf32-i386 
SYMBOL TABLE: 
00000000 g     F .text0000001c main 
00000000         *UND*00000000 funcTest 
再进行编译就能通过了。
[test1@localhost tempCode]$ g++ -o 1 1.cpp cExample.o 
[test1@localhost tempCode]$ ./1 

**********************************************************************
若直接用gcc  对1.cpp 和cExample.c 进行编译链接,会出错。正如上面所说gcc将1.cpp当作c++程序对待,将.c当c程序对待,故生成的符号表中的函数字称不同,链接时会出错。
[test1@localhost tempCode]$ gcc -o 1 1.cpp cExample.c 
/tmp/ccswh6XC.o: In function `main': 
1.cpp:(.text+0x11): undefined reference to `funcTest(int)' 
collect2: ld returned 1 exit status 
但用g++ 对1.cpp 和cExample.c 进行编译链接,就不会出错,因为无论是.c还是.cpp,g++都当成c++程序对待了。
[test1@localhost tempCode]$ g++ -o 1 1.cpp cExample.c 
**********************************************************************
**********************************************************************
 C++程序调用C标准库为什么不用加extern C””
由于C++程序要调用C标准库,所以考虑到这一点,在C头文件(.h头文件)中已经做了特殊的处理,即在编译C++程序的时候,对这些C头文件中声明的函数使用C调用机制(extern "C"),而不使用默认的C++调用机制,防止因C++函数调用机制出现在C库中找不到对应的函数的现象。
**********************************************************************
@@@@@@@@@@@@@@@@
参考:G++
基于GCC编译器先准备一些关于C和C++的知识:
gcc和g++的区别
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: