gcc入门教程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

不经意间,GCC已发展到了4.3的版本,尽管在软件开发社区之外乏人闻问,但因为GCC 在几乎所有开源软件和自由软件中都会用到,因此它的编译性能的涨落会直接影响到Linux 、Firefox 乃至于和Apache等几千个项目的开发。因此,把GCC摆在开源软件的核心地位是一点也不为过。另一方面,GCC4.3的出现,正在牵引着广大程序员们的心。如果我们非要用一个词来说明GCC与程序员之间的关系,那无疑是"心随心动"。

历史篇

作为自由软件的旗舰项目,Richard Stallman 在十多年前刚开始写作GCC 的时候,还只是把它当作仅仅一个 C 程序语言的编译器;GCC 的意思也只是GNU C Compiler 而已。经过了这么多年的发展,GCC 已经不仅仅能支持C 语言;它现在还支持Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL语言,以及支持函数式编程和逻辑编程的Mercury 语言,等等。而GCC 也不再单只是GNU C 语言编译器的意思了,而是变成了GNU Compiler Collection 也即是GNU 编译器家族的意思了。另一方面,说到GCC 对于各种硬件平台的支持,概括起来就是一句话:无所不在。几乎所有有点实际用途的硬件平台,甚至包括有些不那么有实际用途的硬件平台。

Gcc 简介

Linux系统下的gcc(GNU C Compiler)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。Gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%~30%。

官方网站:/

gcc是linux的唯一编译器,没有gcc就没有linux,gcc的重要性就不可言喻啦。居然这么重要,那就很值得我们来好好研究下啦。好啦,开始我们的gcc之旅吧!

首先消除gcc和g++误区吧。

gcc和g++都是GNU(组织)的一个编译器。

误区一:gcc只能编译c代码,g++只能编译c++代码

两者都可以,但是请注意:

1.后缀为.c的,gcc把它当作是C程序,而g++当作是c++程序;后缀为.cpp的,两者都会认为是c++程序,注意,虽然c++是c的超集,但是两者对语法的要求是有区别的,例如:#include

int main(int argc, char* argv[]) {

if(argv == 0) return;

printString(argv);

return;

}

int printString(char* string) {

sprintf(string, "This is a test.\n");

}

如果按照C的语法规则,OK,没问题,但是,一旦把后缀改为cpp,立刻报三个错:“printString 未定义”;

“cannot convert `char**' to `char*”;

”return-statement with no value“;

分别对应前面红色标注的部分。可见C++的语法规则更加严谨一些。

2.编译阶段,g++会调用gcc,对于c++代码,两者是等价的,但是因为gcc命令不能自动和C++程序使用的库联接,所以通常用g++来完成链接,为了统一起见,干脆编译/链接统统用g++了,这就给人一种错觉,好像cpp程序只能用g++似的。

误区二:gcc不会定义__cplusplus宏,而g++会

实际上,这个宏只是标志着编译器将会把代码按C还是C++语法来解释,如上所述,如果后缀为.c,并且采用gcc编译器,则该宏就是未定义的,否则,就是已定义。

误区三:编译只能用gcc,链接只能用g++

严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用gcc/g++,而链接可以用g++或者gcc -lstdc++。因为gcc命令不能自动和C++程序使用的库联接,所以通常使用g++来完成联接。但在编译阶段,g++会自动调用gcc,二者等价。

误区四:extern "C"与gcc/g++有关系

实际上并无关系,无论是gcc还是g++,用extern "c"时,都是以C的命名方式来为symbol 命名,否则,都以c++方式命名。试验如下:

me.h:

extern "C" void CppPrintf(void);

me.cpp:

#include

#include "me.h"

using namespace std;

void CppPrintf(void)

{

cout << "Hello\n";

}

test.cpp:

#include

#include

#include "me.h"

int main(void)

{

CppPrintf();

return 0;

}

1. 先给me.h加上extern "C",看用gcc和g++命名有什么不同

[root@root G++]# g++ -S me.cpp

[root@root G++]# less me.s

.globl _Z9CppPrintfv //注意此函数的命名

.type CppPrintf, @function

[root@root GCC]# gcc -S me.cpp

[root@root GCC]# less me.s

.globl _Z9CppPrintfv //注意此函数的命名

.type CppPrintf, @function

完全相同!

2. 去掉me.h中extern "C",看用gcc和g++命名有什么不同

[root@root GCC]# gcc -S me.cpp

[root@root GCC]# less me.s

.globl _Z9CppPrintfv //注意此函数的命名

.type _Z9CppPrintfv, @function

[root@root G++]# g++ -S me.cpp

[root@root G++]# less me.s

.globl _Z9CppPrintfv //注意此函数的命名

.type _Z9CppPrintfv, @function

完全相同!

【结论】完全相同,可见extern "C"与采用gcc/g++并无关系,以上的试验还间接的印证了前面的说法:在编译阶段,g++是调用gcc的。

二:

今天,我们继续gcc之旅吧。上节我们讲了些gcc的历史发展什么的,还有就是gcc与g++的区别。今天我们就从整体上对gcc编译过程有个细致的了解,也好明白他的工作原理,好为以后深入学习研究打下个基础。

gcc的编译流程分为四个步骤,分别为:

·预处理(Pre-Processing)

·编译(Compiling)->hello.i

·汇编(Assembling)->hello.s

·链接(Linking)

以hello.c为例子,在这四个步骤中可以设置选项分别生成hello.i, hello.s, hello.o以及最终的hello文件:

hello.c : 最初的源代码文件;

hello.i : 经过编译预处理的源代码;

hello.s : 汇编处理后的汇编代码;

hello.o : 编译后的目标文件,即含有最终编译出的机器码,但它里面所引用的其他文件中函数的内存位置尚未定义。

hello / a.out : 最终的可执行文件

相关文档
最新文档