[C++]GCC的C++入门(2012-10-28更新)
本文的入门是指GCC的入门,而不是计算机科学的入门,一些概念是不解释的,比如什么是汇编啊之类的。还有本文几乎只涉及GCC对于C++的支持
1. 写在前边
首先给出一个gcc最简单的用法:
编写源文件 test.cpp,然后使用命令 $gcc test.cpp ,gcc将生成 a.out 程序文件,使用命令 $./a.out ,执行编译好的可执行程序
GCC以前是指GNU C Compiler,在那个时期GCC是C语言的编译器,而G++是C++的编译器。现在GCC是指GNU Compiler Collection,是一系列编译器的集合,包括C++的编译器;而G++特指C++的编译器1。
在很久以前,编译器首先将C++代码转为C代码,然后按照C代码的那一套生成出最后的可执行文件。后来的编译器(包含GCC)都不这么做了,C++代码都是编译生成机器码2。
GCC将C++代码转为机器码,理论上需要四个步骤:预处理(preprocessing)、编译(compilation)、汇编(assembly)以及链接(linking)3;四个步骤对应四个主体:预处理器(preprocessor)、编译器(compiler)、汇编器(assembler)以及链接器(linker)。实际情况却不同,预处理与编译其实是一个步骤,共需要三个步骤:预处理&编译、汇编以及链接。GCC按照以上三个步骤,顺序调用了预处理&编译器、汇编器以及链接器,细节如下:
C语言:cc1 -> as -> (collect2 → ld)
C++语言:cc1plus ->as -> (collect2→ld)
GCC可以处理多种语言:C,C++,D...。GCC通过文件扩展名区分语言的种类,例如:扩展名是.c,就会按照C语言操作,扩展名是.cpp,就会按照C++语言操作。
有两个概念容易混淆,理论派们需要注意一下:
编译:编译过程中的一个步骤(将展开的C++代码转为汇编码)也叫编译,要结合上下文判别。
预处理:有些陈旧的编译器将C++代码转换为C代码的过程叫做预处理,GCC已经不这么做了。在文本中,预处理特指编译过程中的一个步骤(展开C++代码中的头文件与宏)。
2. GCC和G++的不同
以前使用G++编译C++程序,GCC编译C程序,而现在GCC也可以编译C++程序了,不过两者还是有所不同。
2.1. 编程语言识别
GCC现在不特指C编译器了,也可以编译多种语言的源文件,包括C++。GCC是根据文件扩展名来确定编程语言的。
以下扩展名会被识别为C语言,同时需要注意的是,Linux下是区分扩展名的大小写的,而Windows不是。:
- .c - C语言源代码文件。注意,扩展名c是小写的。
- .h - C语言头文件。
- .i - 经过预处理而展开的C源代码。
以下扩展名会被识别为C++语言:
- .C, .cc, .cpp/CPP, .c++, .cp, .cxx - C++源代码文件。.C++, .CP, .CXX是否可用待验证。真特么的多啊-_-
- .H, .hh, .hpp/HPP, .h++, .hp, hxx - C++头文件。.HH是否可用待验证。
- .ii - 经过预处理而展开的C++源代码。
如果不知用GCC而使用G++,会将所有源文件强制判定为C++类型。所以使用G++也有其的好处:对于Windows下的VS用户,C++语言的头文件默认是.h,在GCC下会被识别为C语言头文件。如果使用G++,便不会发生歧义了。
2.2. 类库连接
GCC是不会连接默认的C++类库的,必须手动指定(例如-lstd),而G++却不同~
3. GCC命令介绍
GCC的很多参数是泛语言的,我们只介绍适用于C++的。
Linux下很多程序支持参数连接,比如 rpm -ivh ,就是-i(--install,安装)、-v(--verbose,显示冗余信息)和-h(--hash,用#标记显示进度等)的连接。而GCC不支持参数连接,
而且,GCC的参数顺序一般都不怎么重要~~也就是说,有可能部分参数的顺序变了,其执行结果会有所不同,好在这样的情况不多,遇到了尝试变更下参数顺序吧。
Linux新手还要注意,参数是区分大小写的。
4. 常用参数介绍
GCC的参数多如星蕴~恩,我这里没有用“牛毛”,可见确实非常非常的多,要是想全部记住那是不可能滴~就算全部看一遍也是非常蛋疼的事情,所以,只要知道常用的即可~~
4.1. 输入输出、流程控制
-x 文件类型 [文件列表] 指定编程语言
和C++相关的文件类型有:
- c++ : C++源文件
- c++-header : C++头文件
- c++-cpp-output : C
- assembler
- assembler-with-cpp
- none : 默认识别,相当于不使用-x命令
因为C++和C的基友关系,所以把C的也一并列出:
- c : C源文件
- c-header : C头文件
- cpp-output :C输出文件。注意,这个cpp不代表C++,而是是
-E 在编译前结束。输出预处理结果 - 展开的源代码(.i文件)。
-S 在汇编前结束。输出编译器结果 - 汇编码(.s文件)。
-c 在链接前结束。输出汇编器结果 - 可重定位(未链接的)的目标文件(.o文件)。
-x -E
只进行预处理
-x -S
只进行编译
-x -c
只进行汇编
-x
只进行链接
-o 文件名 如果不指定,则根据输出文件的类型,输出不同的默认文件名。
4.2. 编译连接目录控制
-I目录名 添加头文件搜索路径
-L目录名 添加库搜索路径
-l库名 链接指定库
对于库名和库文件的对应关系,大概是这么个规则
。。。
4.3. 库相关
-shared 创建动态库。默认是 -static 创建静态库
-fPIC 生成位置无关码,简单说,就是共享库用的
-Wp,选项[,选项列表] 传递选项给预处理器
-Wa,选项[,选项列表] 传递选项给汇编器
-Wl,选项[,选项列表] 传递选项给链接器
-Wall 显示警告信息。建议初学者加上这个选项。PS:这个不是-Wa选项的扩展,实际它是cc1的选项。
-g 加入调试信息
-v 打印冗余信息。
-### 打印冗余信息。这个可以查看GCC的子命令。
--version 显示GCC的版本等信息
@文件名 从文件中读取参数
5. 和GCC有关的一些命令
5.1. 静态库相关
ar -rs 档案文件名 对象列表(' ') 创建新的档案。-r 如果已经存在,则更新其中的对象。s 创建索引。
5.2. 动态库相关
ldd 可执行文件名 查看可执行文件对动态库的需求
1. The abbreviation GCC has multiple meanings in common use. The current official meaning is “GNU Compiler Collection”, which refers generically to the complete suite of tools. The name historically stood for “GNU C Compiler”, and this usage is still common when the emphasis is on compiling C programs. Finally, the name is also used when speaking of the language-independent component of GCC: code shared among the compilers for all supported languages.
2. Historically, compilers for many languages, including C++ and Fortran, have been implemented as “preprocessors” which emit another high level language such as C. None of the compilers included in GCC are implemented this way; they all generate machine code directly.
3. When you invoke GCC, it normally does preprocessing, compilation, assembly and linking.