【C语言】编译和链接----预处理详解【图文详解】

欢迎来CILMY23的博客喔,本篇为【C语言】文件操作揭秘:C语言中文件的顺序读写、随机读写、判断文件结束和文件缓冲区详细解析【图文详解】,感谢观看,支持的可以给个一键三连,点赞关注+收藏。

前言 

欢迎来到本篇博客,上一篇我们详细介绍C语言中的编译和链接阶段,在C语言中,编译和链接是将源代码转换为可执行文件的关键过程。本期我们将深入了解这个过程中的预处理阶段。

上一篇博客链接:

【C语言】编译和链接----从源代码到可执行程序的转换-CSDN博客

文章目录

一、预定义符号

 二、#define定义常量

三、 #define 定义宏 

四、 带有副作用的宏参数

五、 宏替换的规则

六、宏和函数的对比

七、 #和##

7.1  #运算符

7.2 ##运算符 

八、 命名约定

九、 #undef

十、 命令行定义

十一、 条件编译 

十二、 头文件的包含 

12.1 本地头文件的包含

12.2 库文件的包含

12.3 二者的区别

 十三、 其他预处理指令


 一、预定义符号

 C语言设置了⼀些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的

 //__FILE__    //进行编译的源文件
 //__LINE__    //文件当前的行号
 //__DATE__    //文件被编译的日期
 //__TIME__    //文件被编译的时间
 //__STDC__    //如果编译器遵循ANSI C,其值为1,否则未定义

例如:

#include<stdio.h>

int main()
{
	printf("%s\n", __FILE__);
	printf("%d\n", __LINE__);
	printf("%s\n", __DATE__);
	printf("%s\n", __TIME__);
	//printf("%d", __STDC__);
	return 0;
}

 由于Visual Studio 2019编译器不遵循ANSI C,是未定义的。所以我们注释掉该行,如果是在gcc编译器,则__STDC__就为1

结果如下所示:

 二、#define定义常量

 #define定义常量的语法如下:

#define name  stuff

#define name stuff 将创建一个名为 name 的符号常量,其为 stuff。 

 因为在预处理阶段,文件会将#define展开和删除,所以我们可以通过gcc编译器来观察

gcc test.c -E -o test.i 

 C1,C2和Num都被替换了

那在使用#define的时候,我们需要注意几个点

1.用来省略for循环判断部分的时候,循环条件的判断恒为真,这个循环是死循环

例如:

#define forever for(;;)

 2.最好不用加分号

例如:

#define MAX 1000; 
#define MAX 1000

会将MAX替换成1000;这样会导致在语句后本来就有分号的情况下,替换后导致多出了一个分号 

 出现语法错误

三、 #define 定义宏 

#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏 (definemacro) 

常规解释: 

在C语言中,定义宏(Macro)指的是使用#define预处理指令为一个标识符(通常是一个常量、函数或代码片段)定义一个符号名称,以便在代码中多次使用,并在预处理阶段进行替换。宏可以是简单的标识符或者带参数的宏。

通过定义宏,可以使代码更具有可读性和可维护性,同时也可以减少代码中的重复性内容,方便后续的修改和维护。定义宏可以用于创建常量、简化复杂表达式、定义函数等。

下面是宏的声明方式: 

#define name( parament-list ) stuff

其中的  parament-list 是⼀个由逗号隔开的符号表,它们可能出现在stuff中。
注意:
参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。 

 例如:

#include<stdio.h>
#define SQUARE( x )  x * x

int main()
{
	int a = SQUARE(5);
	printf("%d\n", a);
	return 0;
}

 这个宏接收一个参数  x
如果在上述声明之后,你把SQUARE( 5 ); 置于程序中,预处理器就会用下面这个x*x表达式替换上面的表达式

但是这个宏存在一定的问题

假设我们传入的是5+2

SQUARE(5+2);

那么这个式子就会被替换成5+2*5+2

 #define SQUARE( 5 + 2 )  5 + 2 * 5 + 2

原意我们是想把这个式子,算成7*7,但是结果却是十七,

那为了解决这个问题,我们就加括号

#define SQUARE( x )  ((x) * (x))

这样才能正确计算表达式的值

所以对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的 操作符或邻近操作符之间不可预料的相互作用。

四、 带有副作用的宏参数

当宏参数在宏的定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值