Linux学习 02 GCC相关

129 阅读2分钟

一、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