一、gcc简介
1.gcc介绍
gcc 原名 GNU Compiler Collection GNU编译套件。是由GNU开发的编译器。
2.使用gcc编译test.c文件
nowcoder@nowcoder:~/Linux$ cd lession02/
nowcoder@nowcoder:~/Linux/lession02$ ls
test.c
nowcoder@nowcoder:~/Linux/lession02$ gcc test.c -o app
nowcoder@nowcoder:~/Linux/lession02$ ls
app test.c
nowcoder@nowcoder:~/Linux/lession02$ ./app
Hello World
首先使用gcc test.c -o app,生成app可执行文件。
然后使用gcc test.c,不适用 -o命令,生成的是带.out的文件
nowcoder@nowcoder:~/Linux/lession02$ gcc test.c
nowcoder@nowcoder:~/Linux/lession02$ ls
a.out app test.c
nowcoder@nowcoder:~/Linux/lession02$ ./a.out
Hello World
3. gcc和g++的区别
1)gcc和g++都可以编译C++程序,但需要注意在链接阶段,gcc不能 自动 链接到C++程序使用的库连接。
2)在编译阶段,gcc和g++二者等同。或者说,在编译阶段,g++就是通过调用gcc来执行的。但因为gcc不能自动链接到C++库,所以通常用g++来编译/链接c++程序。
3)gcc同样可以编译/链接C++程序 需要使用 gcc -lstdc++ 命令,使gcc可以链接到c++程序使用的库连接。
编译阶段:用 gcc 和 g++ 都可以
链接阶段:用 gcc -lstdc++ 和 g++ 都可以
4)关于__cplusplus宏
__cplusplus宏标志着编译器会把代码按照C++语法解释。
g++和gcc都会生成这个宏。
g++编译.c.c++文件都会生成这个宏,gcc只有在编译.cpp文件时会生成这个宏。
二、gcc工作流程
gcc工作有四步流程:预处理、编译、汇编、链接
1. 预处理
代码源文件,经过预处理器变成预处理后源代码,生成 .i 文件。预处理的作用是把头文件加到cpp里面,宏替换,去掉注释等等。
#include<stdio.h>
#define PI 3.14
int main()
{
//这是测试代码
int sum = PI + 10;
printf("Hello World\n");
return 0;
}
这里面预处理要做的是加载include的内容,去掉注释,还有 define的宏进行替换。下面展示一下预处理之后的内容
nowcoder@nowcoder:~/Linux/lession02$ gcc test.c -E -o test.i
nowcoder@nowcoder:~/Linux/lession02$ ls
a.out app test.c test.i
extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
# 840 "/usr/include/stdio.h" 3 4
extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 868 "/usr/include/stdio.h" 3 4
# 2 "test.c" 2
# 5 "test.c"
int main()
{
int sum = 3.14 + 10;
printf("Hello World\n");
return 0;
}
这个文件是不全的,前面有特别多的内容是加载的stdio。后面可以看到define PI 3.14的宏被替换了。最后之前写的注释内容也没了。
2. 编译:
预处理后的代码文件,经过编译器编译变成汇编代码。是.s文件。
nowcoder@nowcoder:~/Linux/lession02$ gcc test.i -S -o test.s
nowcoder@nowcoder:~/Linux/lession02$ ls
a.out app test.c test.i test.s
下面是展开后的一部分汇编代码
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $13, -4(%rbp)
leaq .LC0(%rip), %rdi
call puts@PLT
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
3. 汇编:
将汇编代码汇编成计算机可识别的二进制文件,甚至可以直接执行
nowcoder@nowcoder:~/Linux/lession02$ gcc test.s -s -o test.o
nowcoder@nowcoder:~/Linux/lession02$ ls
a.out app test.c test.i test.o test.s
nowcoder@nowcoder:~/Linux/lession02$ ./test.o
Hello World
4. 链接
通过链接器把一些静态、动态库之类的通过链接器链接在一起,生成可执行文件。
注意:gcc的这些中间步骤是会自动进行的,比如跳过预处理,直接进行编译,生成汇编文件。
nowcoder@nowcoder:~/Linux/lession02$ gcc test.c -S
nowcoder@nowcoder:~/Linux/lession02$ ls
test.c test.s