很多人在第一次接触到C语言的时候是在windows的集成开发环境中学的。把写好的C语言程序放到开发环境中,点一下编译按钮就会帮你生成编译好的可执行程序,这个过程看似非常简单,但是其背后需要经过很多的步骤。其具体步骤可以分为预编译,编译,汇编,链接四部。
下面我们就在Linux中利用gcc编译器来简单的了解一下一个C文件是如何被编译成一个可执行程序的。
首先我们先来写两个简单的C程序
a.c程序

#include <stdio.h>
#define ADD(a,b) (a + b)  // 宏定义
extern int globe_B; // 外部声明b.c中的全局变量
int main(void)
{printf("globe_B = %d\r\n",globe_B);  // 打印出globe_B的值printf("ADD(4,5) = %d\r\n",ADD(4,5));  // 打印出,ADD(4,5)的值
}

b.c程序

int globe_B = 50;

上面两个程序很简单,a.c程序只是简单得打印出globe_B的值和打印出ADD宏定义的值。b.c程序只定义一个globe_B的全局变量。

  • 预编译
    首先来看预编译,预编译的作用是把程序中的宏定义、头文件全部展开、处理条件编译的真假值、去掉注释等作用,最后预编译得到的是一个纯净的C文件。
    在gcc中利用gcc -E xxx.c -o xxx.i得到预编译后的文件。
    下面来对a.c文件进行预编译
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "a.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 367 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 410 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 411 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 368 "/usr/include/features.h" 2 3 4
# 391 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 392 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4/********************省略***********************/extern int globe_B;
int main(void)
{printf("globe_B = %d\r\n",globe_B);printf("ADD(4,5) = %d\r\n",(4 + 5));
}

因为头文件stdio预编译后会展开变成800多行的代码,所以就省略了大部分程序。可以看到a.c被预编译后,注释已经消失了,在第二个printf的ADD宏定义也被展开了,条件编译大家可以自行进行实验。

  • 编译
    编译是在第一步预编译的基础上,对C文件进行语法和语义检查,排除掉有错误的语句,最后得到的是汇编文件
    在gcc中利用gcc -S xxx.i -o xxx.s得到预编译后的文件。
    下面对a.i文件进行编译
.file    "a.c".section .rodata
.LC0:.string    "globe_B = %d\r\n"
.LC1:.string    "ADD(4,5) = %d\r\n".text.globl   main.type   main, @function
main:
.LFB0:.cfi_startprocpushq   %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq    %rsp, %rbp.cfi_def_cfa_register 6movl   globe_B(%rip), %eaxmovl %eax, %esimovl  $.LC0, %edimovl $0, %eaxcall    printfmovl  $9, %esimovl    $.LC1, %edimovl $0, %eaxcall    printfmovl  $0, %eaxpopq    %rbp.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE0:.size main, .-main.ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609".section    .note.GNU-stack,"",@progbits

汇编得到的是跟机器架构相关的汇编语言。

  • 汇编
    汇编的作用是把第二步生成的汇编文件转化成目标文件,也就是二进制文件。
    在gcc中用gcc -c xxx.s -o xxx.o生成
    由于生成的文件是二进制文件,所以一般的文本工具不能打开,必须要用一些二进制查看软件才可以,常用的有winhex。

    上面是用winhex打开的a.o二进制文件。

  • 链接
    链接是把第三步中生成的所有目标文件全部链接成一个可执行文件。在链接的时候链接器会把各个文件中的函数,变量一一对应,如果某个变量或函数没有做外部声明就会报链接错误。
    在gcc中用gcc xxx.o -o xxx.out生成

    最后链接出来的可执行文件运行正常。

在实际开发中常用gcc xxx.c -o xxx.out一步到位直接生成可执行文件。

C语言的编译,汇编和链接相关推荐

  1. c语言编辑编译链接,C语言的“编译、链接”

    我们写的代码,仅仅是文本文件(txt),不管后缀怎么变,终究是文本文件,计算机只能显示,不能做事(执行). 文本文件通过"编译.链接",成为可执行文件(windows下是exe): ...

  2. 易语言静态编译链接器大全(为EIDE助手准备滴)

    点击阅读原文 本文中的各个链接器收集于网络,汇总在一起,方便广大易友下载使用: 易语言的大部分支持库是 使用 vc6 编译, 所以, 推荐大家使用 vc6的链接器: 如果使用 其他链接库编译出现问题, ...

  3. python语言不用编译_python程序不需要编译吗

    python编译过程和执行原理 (1)python执行原理 这里的解释执行是相对于编译执行而言的.我们都知道,使用C/C++之类的编译性语言编写的程序,是需要从源文件转换成计算机使用的 机器语言,经过 ...

  4. 【C 语言】编译过程 分析 ( 预处理 | 编译 | 汇编 | 链接 | 宏定义 | 条件编译 | 编译器指示字 )

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  5. Linux下C语言执行过程(预处理,编译,汇编,链接,执行)

    1.C语言的执行过程包括5个步骤:分别是:预处理,编译,汇编,链接,执行 第一步:编写C源代码,截图如下: 2.预处理,命令为:gcc -E variable.c -o variable.i(这步的作 ...

  6. C语言的预处理、编译、汇编、链接

    2019独角兽企业重金招聘Python工程师标准>>> 一.预处理 预处理指令的执行主要包含下列事情: 1.头文件的包含 2.注释的删除 3.宏定义的替换 4.条件编译的选择 指令: ...

  7. c语言程序的生命周期(编写、预处理、编译、汇编、链接、执行)

    目录 程序的生命周期 一.引言 二.程序经历的六个阶段 1.阶段一:编辑(Edit) 2.程序编译系统(Programs Compilation System) 阶段二:预处理(Preprocess) ...

  8. C语言 程序的翻译 预处理 编译 汇编 链接 #define详解

    1.程序的翻译环境和执行环境 执行环境:所在操作系统的平台 win10 win11 linux 翻译环境:MSVC gcc g++ 你的vs 2019 和2022 是集成开发环境把编辑器编译器全部给你 ...

  9. c语言编译过程详解,预处理,编译,汇编,链接(干货满满)

    楔子 我们在各自的电脑上写下代码,得明白我们代码究竟是如何产生的,不想了解1,0什么的,但这几个环节必须掌握吧. 我们的代码会经过这4个环节,从而形成最终文件,c语言作为编译语言,用来向计算机发出指令 ...

最新文章

  1. 什么是Unwind segues,您如何使用它们?
  2. PostgreSQL 务实应用(三/5)分表复制
  3. 关于sublime-text-2的Package Control组件安装方法,自动和手动
  4. Android笔记之自定义Editext
  5. idea中git分支、合并与使用
  6. 2017android 最强旗舰,2017年世界六大旗舰机,华为第五,第一惊艳全球!
  7. js 滚动条自动滚动到最底部
  8. 【报告分享】2020全球网络趋势报告.pdf(附下载链接)
  9. 如何进阶一名有竞争力的程序员?
  10. 实验4-1-2 求奇数和 (15 分)
  11. Python爬虫之(三)urllib库
  12. js 中 ! + - ~ 符号和匿名函数
  13. DB9串口定义及含义
  14. 【Matlab绘图】plot3函数绘制三维点或线图
  15. Oracle get、start、edit、spool命令,临时变量、已定义变量
  16. WebApp实时开源框架Clouda入门使用与记录
  17. 【面试题集 —— No.01】常见图片格式BMP、JPG/JPEG、PNG、GIF、TIFF、SVG的区别
  18. 开启和关闭远程Windows系统3389端口
  19. B-010 详细解析电源滤波电容的选取与计算
  20. 《短线交易秘诀》读后感

热门文章

  1. Mac照片后期处理软件软件:Capture One 21 Pro
  2. 学习Figma心得体会
  3. ASP.NET 调试出现%@ Application Codebehind=Global.asax.cs Inherits=XXX.XXX.Global Language=C# %...
  4. PHP-为图片再添加水印图片
  5. 如何理解线程与进程(含有通俗解释)
  6. setInterval影响性能导致卡死的解决方法
  7. vue+element制作音乐播放器播放进度条bug(鼠标拖拽slider滑块滑动到指定位置无效)
  8. Python 实现微信防撤回功能
  9. Sparse Virtual Texture (虚拟贴图技术)
  10. vba连接mysql代码_vba 连接数据库代码