笔记:C语言的编译过程详解

前言

C语言是编译性的语言,所以说C语言程序要运行有一个必不可少的过程——编译,这篇笔记解释了我对C语言编译过程的理解

c语言编译过程大概分为以下几个流程,预处理=》编译=》=汇编=》链接,接下来就会详细分析一下上面的过程

预处理

简单来说,C语言的预处理的过程有点类似于文本的替换,即将源代码文件中的#开头的命令来进行替换,比如将 #include替换为其真正的内容,预处理之后源代码文件仍然还是一个文本文件,只不过比之前的文件大的多了。一般找不到库文件的问题会在这个阶段进行报错

编译

接下来就是重头戏了,编译阶段。在这个阶段,编译器首先先来检查程序中是否有语法错误(不是逻辑错误哦!),如果有的话便抛出错误,没有的话便会将预处理器生成的代码将被转化为对应的汇编代码,注意注意,这里的汇编代码我们人仍然能够勉强看懂。以下举个小例子

首先假设有一个C语言程序,源代码如下,文件名被命名为了 1.c

int main()
{
        int i = 0;
        printf("i = %d",i);
        return 0;
}

然后在编译过程中加入-S参数(使用gcc编译),让gcc在编译到汇编过程就停止,然后就会在1.c文件的旁边出现了一个叫做1.s的文件,这个文件的内容如下(运行环境ubuntu 22.04)


        .file   "1.c"
        .text
        .section        .rodata
.LC0:
        .string "i = %d"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        endbr64
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    $0, -4(%rbp)
        movl    -4(%rbp), %eax
        movl    %eax, %esi
        leaq    .LC0(%rip), %rax
        movq    %rax, %rdi
        movl    $0, %eax
        call    printf@PLT
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
        .section        .note.GNU-stack,"",@progbits
        .section        .note.gnu.property,"a"
        .align 8
        .long   1f - 0f
        .long   4f - 1f
        .long   5
0:
        .string "GNU"
1:
        .align 8
        .long   0xc0000002
        .long   3f - 2f
2:
        .long   0x3
3:
        .align 8
4:

以上就是汇编的代码

汇编

这个阶段,编译器便将刚刚“编译”阶段产生的汇编代码翻译成机器所能理解的2进制文件

链接

链接过程中编译器将多个源代码文件以及库文件(.lib或.so)链接在一起,生成出最终的结果.out文件或者.exe文件

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议,记得载明出处,(期待)。内容有问题?点此反馈
上一篇
下一篇