当前位置: 首页 > news >正文

C语言编译过程详解

以Linux下C语言的编译过程为例  https://zhangvalue.blog.csdn.net/article/details/84983836

编译过程:gcc

gcc命令其实依次执行了四步操作:1.预处理(Preprocessing), 2.编译(Compilation), 3.汇编(Assemble), 4.链接(Linking)

gcc helloword.c

通过gcc 生成可执行文件.out 文件

程序代码如下:

// test.c
#include <stdio.h>
#include "mymath.h"// 自定义头文件
int main(){
    int a = 2;
    int b = 3;
    int sum = add(a, b); 
    printf("a=%d, b=%d, a+b=%d\n", a, b, sum);
}

头文件定义:

// mymath.h
#ifndef MYMATH_H
#define MYMATH_H
int add(int a, int b);
int sum(int a, int b);
#endif

头文件实现:

// mymath.c
int add(int a, int b){
    return a+b;
}
int sub(int a, int b){
    return a-b;
}

1.预处理(Preprocessing)

预处理用于将所有的#include头文件以及宏定义替换成其真正的内容,预处理之后得到的仍然是文本文件,但文件体积会大很多。gcc的预处理是预处理器cpp来完成的,你可以通过如下命令对test.c进行预处理:

gcc -E -I./inc test.c -o test.i

或者直接调用cpp命令

$ cpp test.c -I./inc -o test.i

上述命令中-E是让编译器在预处理之后就退出,不进行后续编译过程;-I指定头文件目录,这里指定的是我们自定义的头文件目录;-o指定输出文件名。

经过预处理之后代码体积会大很多:

X文件名文件大小代码行数
预处理前test.c146B9
预处理后test.i17691B857

预处理之后的程序还是文本,可以用文本编辑器打开。

2.编译(Compilation)

这里的编译不是指程序从源文件到二进制程序的全部过程,而是指将经过预处理之后的程序转换成特定汇编代码(assembly code)的过程。编译的指定如下:

$ gcc -S -I./inc test.c -o test.s

上述命令中-S让编译器在编译之后停止,不进行后续过程。编译过程完成后,将生成程序的汇编代码test.s,这也是文本文件,内容如下:


// test.c汇编之后的结果test.s
    .file   "test.c"
    .section    .rodata
.LC0:
    .string "a=%d, b=%d, a+b=%d\n"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $32, %esp
    movl    $2, 20(%esp)
    movl    $3, 24(%esp)
    movl    24(%esp), %eax
    movl    %eax, 4(%esp)
    movl    20(%esp), %eax
    movl    %eax, (%esp)
    call    add 
    movl    %eax, 28(%esp)
    movl    28(%esp), %eax
    movl    %eax, 12(%esp)
    movl    24(%esp), %eax
    movl    %eax, 8(%esp)
    movl    20(%esp), %eax
    movl    %eax, 4(%esp)
    movl    $.LC0, (%esp)
    call    printf
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret 
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits

3.汇编(Assemble)

汇编过程将上一步的汇编代码转换成机器码(machine code),这一步产生的文件叫做目标文件,是二进制格式。gcc汇编过程通过as命令完成:

$ as test.s -o test.o

等价于:

gcc -c test.s -o test.o

这一步会为每一个源文件产生一个目标文件。因此mymath.c也需要产生一个mymath.o文件

4.链接(Linking)

链接过程将多个目标文以及所需的库文件(.so等)链接成最终的可执行文件(executable file)

命令大致如下:

$ ld -o test.out test.o inc/mymath.o ...libraries...

结语

经过以上分析,我们发现编译过程并不像想象的那么简单,而是要经过预处理、编译、汇编、链接。尽管我们平时使用gcc命令的时候没有关心中间结果,但每次程序的编译都少不了这几个步骤。也不用为上述繁琐过程而烦恼,因为你仍然可以:

$ gcc hello.c # 编译
$ ./a.out # 执行
 

相关文章:

  • Clion编写第一个C程序
  • C语言输入一串数据到数组中,用空格隔开回车结束
  • C语言-判断字符串b的所有字符是否都在字符串a中出现过
  • C语言:判断A+B和C的关系
  • PV、UV、VV、IP的区别
  • C语言中输入函数(scanf()、fgets()和gets())的区别详解
  • c语言中getchar()
  • C语言-static的作用
  • C语言-2019年九1
  • C语言-2019年九题2
  • C语言-2018年第九题1
  • C语言比Java、Python高效
  • C语言-比较字符串是否相等
  • C语言里指针和引用的区别
  • 大数据平台数据集市
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • Hibernate【inverse和cascade属性】知识要点
  • JavaScript DOM 10 - 滚动
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • mysql中InnoDB引擎中页的概念
  • node入门
  • Rancher-k8s加速安装文档
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • 关于extract.autodesk.io的一些说明
  • 理清楚Vue的结构
  • 实现菜单下拉伸展折叠效果demo
  • 算法---两个栈实现一个队列
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • ​批处理文件中的errorlevel用法
  • #1015 : KMP算法
  • #考研#计算机文化知识1(局域网及网络互联)
  • (007)XHTML文档之标题——h1~h6
  • (1)Nginx简介和安装教程
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (生成器)yield与(迭代器)generator
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .Net Web项目创建比较不错的参考文章
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • .sh文件怎么运行_创建优化的Go镜像文件以及踩过的坑
  • /proc/interrupts 和 /proc/stat 查看中断的情况
  • @Responsebody与@RequestBody
  • [ Linux ] git工具的基本使用(仓库的构建,提交)
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
  • [3D游戏开发实践] Cocos Cyberpunk 源码解读-高中低端机性能适配策略
  • [ai笔记9] openAI Sora技术文档引用文献汇总
  • [BZOJ2208][Jsoi2010]连通数
  • [C#]无法获取源 https://api.nuge t.org/v3-index存储签名信息解决方法
  • [c#基础]DataTable的Select方法
  • [CC-FNCS]Chef and Churu