1.gcc支持编译的一些源文件后缀名
后缀 | 源文件 |
---|---|
.c | C语言源文件 |
.C .cc .cxx | C++源文件 |
.m | Object-C源文件 |
.i | 经过预处理后的C源文件 |
.ii | 经过预处理后的C++源文件 |
.s .S | 汇编语言源文件 |
.h | 预处理文件(头文件) |
.o | 目标文件 |
.a | 存档文件 |
2.gcc编译程序的流程
源文件—>预处理—>编译—>汇编—>链接—>可执行文件
3.用gcc编译一个经典C程序
gedit hello.c //新建
在新建的hello.c文件中输入一下代码:
// filename: hello.c
#include <stdio.h>
int main(int argc, char **argv)
{
printf("Hello, World");
return 0;
}
下面用gcc编译.c文件
gcc hello.c -o hello
从程序员的角度来看,一个简单的-o选项可以省略很多中间步骤一次性输出可执行文件; 但从编译器的角度来看,这条命令的背后是一系列的繁杂的工作。
4.gcc到底背着我们做了什么
首先gcc会调用预处理程序cpp,由它负责展开在源程序中定义的宏(上例:#include ),向其中插入#include语句所包含的内容(原地展开stdio.h包含的代码)
在Xfce终端中输入
gcc -E hello.c -o hello.i
还记得.i后缀吗?hello.i这是一个经过预处理器处理之后的C源文件,在bash试试这个命令,然后用vim打开它。
gcc的-E参数可以让gcc在预处理结束后停止编译过程。
第二步,将hello.i编译为目标代码,gcc默认将.i文件看成是预处理后的C语言源代码,因此它会直接跳过预处理,开始编译过程。
gcc -c hello.i -o hello.o
同样,用vim打开.o文件看看和.i .c文件有什么不同?应该是一片乱码,是吧?(它已经是二进制文件了)
- 请记住,gcc预处理源文件的时候(第一步),不会进行语法错误的检查
- 语法检查会在第二步进行,比如花括号不匹配、行末尾没有分号、关键字错误……
第三步,gcc连接器将目标文件链接为一个可执行文件,一个大致的编译流程结束
gcc hello.o -o hello
4.gcc编译模块化的程序
现在很多软件都是采用的模块化开发,通常一个程序都是有很多个源文件组成,相应的就形成了多个编译单元。gcc能够很好的处理这些编译单元,最终形成一个可执行程序
1. 新建hello.h文件
// hello.h
extern void print();
- 新建hello_print.c文件
// hello.c
#include <stdio.h>
void print()
{
printf("Hello, World!\n")
}
- 新建hello_main.c文件
// hello_main.c
#include "hello.h"
int main()
{
print();
return 0;
}
- 编译模块化程序
gcc -c hello_print.c hello_main.c -o hello
上面的一条命令实际上执行了以下内容:
gcc -c hello_print.c -o hello_print.o
gcc -c hello_main.c -o hello_main.o
gcc hello_print.o hello_main.o -o hello