你是否有思索过我们写的C代码是如何被编译器给执行起来的呢?
在此过程中计算机又干了些什么呢?
windows 下C语言执行过程:
.c文件-->预编译-->编译-->链接-->可执行文件.exe
什么是预编译呢?
编译器会对头文件包含指令(例如#include “my_add”)、宏定义指令(如#define …)、条件编译指令(如#ifdef,#ifndef等,见下)等做相应的处理;
对于头文件包含指令,编译器会将该头文件里面包含的信息直接替换掉这条令;
对于宏定义,例如#define N 10,预编译器则会直接将源代码中的N直接替换成10;
(去注释)对于条件编译指令,则是为了对代码的过滤,将不必要的代码过滤掉。简单点说,预编译就是代码内容的替换以及删除掉没用的代码。
什么是编译呢?
编译就是把经过预编译的代码翻译成为机器能够识别的机器语言的过程。
而在编译的过程中,编译器还要对代码做词法分析、语法分析、语义分析、优化、汇编,然后生成机器语言代码。机器语言是用二进制代码表示的计算机能直接识别和执行的一种机器指令的集合。
在windows下,我们可以在我们的项目文件夹下找到一个.obj的文件,这个文件就是我们的目标代码文件。
什么是链接呢?
链接:生成可执行程序 即.exe文件,我们可以在项目文件下的debug文件夹下找到一个.exe文件。
linux下可这样操作查看
- 预处理选项
gcc -E test.c -o test.i
预处理完成之后就停下来,预处理之后产生的结果都放在test.i文件中。- 编译选项
gcc -S test.c
编译完成之后就停下来,结果保存在test.s中。- 汇编选项
gcc -C test.c
汇编完成之后就停下来,结果保存在test.o中.- 链接选项
gcc -O mytest test.o
链接完成之后就停下来,结果保存在mytest中.
若省略mytest默认生成a.out
test.c
test.i
test.s
宏
链接:https://blog.csdn.net/Romantic_C/article/details/79451028
常见的预处理指令
# //空指令,无任何效果
#include //包含一个源代码文件
#define //定义宏
#undef //取消已定义的宏
#if //如果给定条件为真,则编译下面代码
#ifdef //如果宏已经定义,则编译下面代码
#ifndef //如果宏没有定义,则编译下面代码
#elif //else if的简写
#endif //结束一个#if……#else条件编译块
#error //停止编译并显示错误信息
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义
常见的条件编译指令
1.#if 常量表达式
//...
#endif
//常量表达式由预处理器求值。
如:
#define __DEBUG__ 1
#if __DEBUG__
//..
#endif
2.多个分支的条件编译
#if 常量表达式
//...
#elif 常量表达式
//...
#else
//...
#endif
3.判断是否被定义
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
4.嵌套指令
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endif