C的编译和预处理

不知道大家有没有想过这样一个问题,我们写完一个C语言代码,我们的计算机是怎么去识别的,然后输出我们想要的结果,今天我就和大家一起学习这个问题。

程序的编译

我们从写下一个.c文件到计算机输出我们想要的结果一共要经历两个环境:

  1. 翻译环境
  2. 执行环境

翻译环境

在翻译环境中源代码会被转换成可执行的机器指令。而转换成机器指令需要以下几个步骤:

  1. 预编译(预处理)
    预处理主要有:头文件的包含,注释的删除,#define符号的替换。
  2. 编译
    这个阶段就会把C语言的源代码转换成汇编代码,而转换的时候计算机会对我们的代码进行语法分析、词法分析、语义分析、符号汇总。如果大家想对编译这块了解的更深的话可以看看《编译原理》。
  3. 汇编
    汇编会把汇编语言转换成二进制指令,我们的计算机只能读懂二进制语言。在windows环境下会生成.obj文件,而Linux环境下会生成.o文件。
  4. 链接
    每个源文件都会生成一个目标文件,然后统一经过链接器生成可执行程序,windows下后缀为.exe文件
    在这里插入图片描述

运行环境

  1. 程序必须载入内存中。在由操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
  2. 程序的执行便开始。接着调用main函数。
  3. 开始执行程序代码。这个时候程序将使用一个运行时的堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
  4. 终止程序。正常终止main函数,也有可能是意外终止。

程序的预处理

预定义符号

FILE 进行编译的源文件
LINK 源文件中的行号
DATE 文件被编译的日期
TIME 文件被编译的时间
STDC 如果编译器遵循ANSI C ,值为1,否则未定义
在这里插入图片描述
本人用的是vs2019这个编译器不完全遵循ANSI C。

define

这个是一个宏定义的标识符,举个例子:

#define MAX 100
#define reg refister
#define mul(x) x*x
#define mul(x) (x)*(x)

注意:宏定义后面不要带分号
宏定义会在函数预处理阶段就替换成值或者表达式;例如:

#define mul(x) x*x
mul(5)
会被替换成  5*5
2*(5+mul(2+3))//这个表达式的结果是多少?是60吗?答案是32,因为会替换成2*(5+2+3*2+3)

所以用宏定义的时候需要格外注意,尽量带括号。

undef

这条指令用于移除一个宏定义。例如:

#define MAX 100
int main() {
	printf("%d\n", MAX);
	#undef MAX
	printf("%d\n", MAX);

	return 0;
}

在这里插入图片描述
这样MAX就会被取消定义。

条件编译

在C语言中有如下一些这样的指令,例如:

#if
#endif

#if
#elif
#else
#endif

#if defined(symbol)
#ifdef symbol

这些都是一些预编译的条件指令,话不多说直接上代码:

#define FLAG 1
int main() {
#if FLAG
	printf("hello");
#endif
	return 0;
}

这段代码预定义了一个FLAG这个表示符,而#if FLAG就是判断FLAG有没有被定义,如果有就执行下面代码,一直到#endif结束。
在这里插入图片描述
定义了FLAG就会打印hello,没有就不会打印,#if和#endif是成对出现的,不能漏掉任何一个。
而下面这个跟if else用法类似,但是不能混为一谈

就是那个条件满足执行那个,如果都不满足就执行#else后面的代码,最后也是以#endif结束。这些条件编译的预处理指令在实际开发中用到的也是非常多的,这是一个重点,我们在今后的学习中再进行更深入的了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值