文章目录
1. gcc的编译过程
我们C源文件是如何生成可执行文件的:
C源文件 -> 预处理 -> 编译 -> 汇编 -> 链接 -> 可执行文件。
1.1 预处理 :gcc -E xxx.c
使用命令gcc -E xxx.c
,可以对xxx.c
源文件进行预处理。
- 在预编译过程中,主要是处理源文件中以
#
开头的预编译指令。
处理内容一般如下:- 删除#define并展开宏
- 处理所有条件预编译指令,如#if, #ifdef, #endif
- 插入头文件到“#include”处
- 删除所有注释
- 添加行号和文件名标识,以便编译时编译器产生调试用的行号信息
- 保留所有#pragma编译指令。
例如:
对下图的.c源文件进行处理。
可以看到#include<stdio.h>
语句包含的头文件已经展开。
对于//
,/**/
注释的代码,已经删除。
1.2 编译:gcc -S xxx.i
使用命令gcc -E xxx.c
,可以对xxx.c
源文件进行编译,自动编译生成一个.s文件。
查看文件,可观察到这个编译生成的.s
文件是由汇编代码写的汇编文件。
1.3汇编:gcc -c hello.s
使用命令gcc -c xxx.c
,可以对xxx.c
源文件进行编译,自动编译生成一个.o文件。
(gcc 工具会在对xxx.c
文件汇编之前,自动把.c程序预处理、编译)
执行这个命令后,GCC编译工具利用汇编程序as(汇编器)将汇编语言源程序转换成0和1组成的机器指令序列(机器语言程序)
生成了一个.o的目标文件.
vim打开hello.o
文件,并输入命令:%!xxd
将当前文本转化为16进制格式,以查看文件的二进制形式。
或者在linux终端中输入xxd hello.o
也可以查看汇编生成的二进制文件。
1.4 链接:
将多个可重定位的目标文件.o合并以生成可执行文件。生成可执行文件可以被加载到内存中,由系统执行。
Linux终端中输入命令gcc hello.o -o hello
,就可以将hello.o,printf.o(printf.o由gcc编译器自动添加)目标文件链接起来,-o hello
表示生成的可执行文件名字为hello
。
执行完命令后,我们可以看到多了一个绿色的可执行文件hello
1.5 最后,运行可执行文件
使用./xxx
的表达方式运行可执行的文件。
运行可执行文件后,看到在终端打印了hello world
。
总结:
生成可执行的文件分为4步走:预处理 -> 编译 -> 汇编 -> 链接,然后生成可执行文件。
一般来说,直接输入命令gcc xxx.c -o yyy
,就可生成可执行文件yyy
,GCC工具会默认自动先后完成预处理、编译、汇编、链接的操作。
1.6 深入拓展:编译的原理
C语言程序设计编程注意事项
1.头文件包含非常重要,C语言中没有包含头文件就使用函数,使用的函数会默认返回一个int型的返回值。
2.以函数为单位作为程序单位来编写,可以提高代码的复用性。如写+-*/
的功能,可以把+-*/
分成4个程序单位,如以后用到+
法功能,就可以抠+
法的程序单元出来方便复用。
3.main函数是我们人为定义的一个最先开始的线程,在程序运行的适合可以结束。
4.GCC编译器:使用gcc 编译的源文件一定要写后缀,因为gcc 要根据后缀作编译选择(区分文件类型)
5.声明部分+实现部分:C语言推荐 变量先定义后使用
6.进程的返回值:return 0;
和exit(0)
是表示返回一个值给父进程看的。在C语言中,我们习惯用0表示成功,非0表示失败。
7.注释:用一下三种方式实现。
/*
*/
//
#if 0
#endif
8.算法:解决问题的方法。程序:用某种语言实现算法。
算法需要用看得到的方式表达出来,如使用 流程图,NS图,有限状态机FSM 描述出来。
9.防止写越界,防止内存泄漏。谁打开,谁关闭,谁申请谁释放。
10.C语言的建议:
- 概念的正确性
- 动手能力(每天都在成长)(程序员不是培训出来的,像是作家,需要日积月累的)
- 阅读优秀的程序段(先要动手,再去阅读,有对比才有伤害)
- 大量练习,面试题(扎实自己的基本功)