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

GCC编译器查看C语言编译过程

编译过程:

  1. 预处理:预处理器将对源文件中的宏进行展开。
  2. 编译:编译器gcc将c文件编译成汇编文件。
  3. 汇编:汇编器as将汇编文件编译成机器码。
  4. 链接:将目标文件和外部符号进行连接,得到一个可执行二进制文件。

以一个很简单的01_test.c来探讨这个过程。

#include <stdio.h> #define NUMBER (1 + 2) int main(void) { int x = NUMBER; printf("x:%d\n",x); return 0; }
  1. 预处理
    [csy@local compile_test]$ gcc -E -o 01_test.i 01_test.c

用cat查看01_test.i的内容如下:

int main(void) { int x = (1 + 2); printf("x:%d\n",x); return 0; }

可以看到,文件中宏定义NUMBER出现的位置被(1+2)替换掉了,其它的内容保持不变。
2. 编译成汇编代码
gcc -S -o 01_test.s 01_test.i
通过cat test.s查看01_test.s的内容为汇编代码。

[csy@local compile_test]$ cat 01_test.s .file "01_test.c" .section .rodata .LC0: .string "x:%d\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp movl $3, 28(%esp) movl $.LC0, %eax movl 28(%esp), %edx movl %edx, 4(%esp) movl %eax, (%esp) call printf movl $0, %eax leave ret .size main, .-main .ident "GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)" .section .note.GNU-stack,"",@progbits
  1. 使用汇编器编译成机器码
[csy@local compile_test]$ gcc -c -o 01_test.o 01_test.s

生成的机器码:

ELF ? 4 ( U夊冧饍?荄$ ? 婽$塗$?$椟? 擅 x:%d GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4) .symtab .strtab .shstrtab .rel.text .data .bss .rodata .comment .note.GNU-stack 4 - X % d + d 0 d 8 0 j - A ? ? Q ? ? @ ? - 01_test.c main printf "
  1. 使用链接器把目标文件链接成可执行文件
    将所有的 .o文件链接起来生成可执行程序。
    [root@zhifachen test]# gcc -o 01_test.exe 01_test.o

运行:

[csy@local compile_test]$ ./01_test.exe x:3

编译过程小结

预处理阶段:对包含的头文件(#include)和宏定义(#define、#ifdef等)进行处理
gcc -E-o 01_test.c 01_test.i
//-o表示输出为指定文件类型 -E将源文件(.c)转换为(.i)
编译阶段:检查代码规范性、语法错误等,在检查无误后把代码翻译成汇编语言
gcc -S -o 01_test.i 01_test.s
//-S将已预处理的C原始程序(.i)转换为(.s)
汇编阶段:
gcc -c -o 01_test.o 01_test.s
//将汇编代码编译成机器码
链接阶段:将目标文件整合起来链接为可执行程序
gcc -o 01_test.exe 01_test.o
//将机器码(.o)和一些库函数整合成(.exe)

gcc常用选项

快速编译示例:
预编译,生成已预编译过的C原始程序*.i

gcc -E gcc_test.c -o gcc_test.i

编译,生成汇编语言原始程序*.s

gcc -S gcc_test.i -o gcc_test.s

编译,生成目标文件*.o

gcc -c -o 01_test.o 01_test.s

链接,生成可执行程序

gcc -o 01_test.exe 01_test.o

方法二:
编译

gcc -c gcc_test.c -o gcc_test.o

链接

gcc -o gcc_test.exe gcc_test.o

运行测试程序

./gcc_test.exe

方法三:
编译并链接

gcc -o gcc_test.exe gcc_test.c

运行测试程序

[csy@local compile_gcc]# ./gcc_test.exe MAX=100 max(3,4)=4

编译时候传递全局宏定义示例

在代码中可以直接使用#define 来定义一个宏,然后在代码中引用,有时候我们希望通过编译时候决定编译宏内容,以及宏是否定义,这时候可以通过编译时候 -D 选项来指定。
hello.c源码

#include <stdio.h> int main(void) { #ifdef CSY//表示如果定义了CSY,即命令行参数传了CSY,就执行下面的输出 printf("CSY is defined!\n"); #else printf("CSY is not defined!\n"); #endif printf("main exit\n"); return 0; }

条件编译,用-D传递,如果没有传CSY则执行#else

[csy@local compile_gcc]# gcc -o hello hello.c -DCSY [csy@local compile_gcc]# ./hello.exe CSY is defined! main exit
http://www.jsqmd.com/news/1281118/

相关文章:

  • 物联网设备初级电池寿命优化方案与低功耗设计实践
  • UnityEngine.UI程序集丢失:系统性排查与解决方案全解析
  • 网上那么多订票攻略,到底怎么买特价机票才真实有效? - 工具软件使用方法推荐
  • MATLAB实现电-热综合能源系统两阶段优化调度
  • 如何彻底掌控Windows窗口:Window Resizer终极桌面管理指南
  • Maven 常用的jar包依赖
  • AI产品的客户留存率提升实践:从数据预警到主动干预的运营体系
  • 3步快速部署IPBan:免费高效的服务器安全防护终极方案
  • NBM5100A与TM4C129LNCZAD在低功耗物联网设备中的协同设计
  • 三步掌握Project Graph:免费跨平台节点图工具终极指南
  • 如何在电脑上流畅运行Switch游戏?Ryujinx模拟器终极指南
  • 企业级中文LLM实战:从微调到部署全流程解析
  • 从宝可梦到无人机:AI训练数据的非传统来源与工程挑战
  • 绝区零蕾米埃尔培养材料介绍 蕾米埃尔培养需要什么材料
  • Spring Boot高校离校系统开发实践与架构设计
  • 渔人的直感:FF14钓鱼计时器的终极指南
  • NBM5100A芯片在低功耗物联网设备中的高效电源管理方案
  • 如何在Windows上直接运行安卓应用?APK安装器终极指南
  • 微信支付wx.pay核心配置参数详解与安全实践
  • “与法同行”普法网站的设计与实现
  • 网络安全职业转型指南:从零基础到高薪就业
  • 工业物联网设备低功耗电源管理方案设计与优化
  • Kubernetes Pod 一直 Pending 排查全流程:从 describe events 到资源、污点、PVC 逐层定位
  • Nginx安全防护与HTTPS部署实战:从基础配置到纵深防御
  • Citra 3DS模拟器:在电脑上玩转任天堂3DS游戏的终极指南 [特殊字符]
  • 5分钟快速上手:GoldHEN金手指管理器终极使用指南
  • 3分钟极速上手!免费网盘直链下载助手完整指南:一键获取9大平台真实下载地址
  • 如何快速设计完美农场:3步掌握星露谷物语农场规划器终极指南
  • 物联网设备低功耗电源管理方案与优化实践
  • 实战指南:Spek音频频谱分析器的深度解析与完整部署方案