【C语言深度解剖】阅读笔记 预处理

本文详细介绍了C语言中的预处理指令,包括宏定义的使用,如数值宏定义、字符串宏常量、表达式宏定义等,以及条件编译的三种形式。此外,还讨论了文件包含、#error指令、#line指令和#pragma预处理指令的功能和应用场景。预处理在编译过程中的作用和技巧对于优化代码和提高效率至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.宏定义

2.条件编译

3.文件包含

4.#error 预处理指令

5.#line

6.#pragma 预处理

7.#运算符

8.##运算符


1.宏定义

1.1数值宏定义

const 修饰的数据是有类型的,而 define 宏定义的数据没有类型。

建议以后在定义一些宏常数的时候用 const 代替,编译器会给 const 修饰的只读变量做类型校验,减少错误的可能。

const 修饰的只读变量不能用来作为定义数组的维数, 也不能放在 case 关键字后面//C语言规定数组下标必须是常量,只读变量也不可以

1.2字符串宏常量

经常使用定义路径上,注意宏定义只是简单的替换,因此路径不需要加双引号

#define ENG_PATH_4 E:\\English\\listen_to_this\\listen_to_this_3

1.3不能用define宏定义注释符号,因为注释的处理先于预处理指令,所以不能用宏定义代替//、/*、*/

1.4用 define 宏定义表达式

宏函数被调用时是以实参替代形参,而不是值传送。

举例#define SQR (x)  x * x

如果x=10+1,SQR (x)被替换后变成 10+1*10+1

解决办法:#define SQR (x) ((x)*(x))//注意最外层的括号也不要省略

1.5#define SUM (x) (x)+(x)SUM后面的第一个空格会被省略,后面一个不会

1.6#undef 撤销宏定义

#define PI 3.141592654

#undef PI

{

#define X 3

#define Y X*2

#undef X

#define X 2

int z=Y;

z 的值为多少?

z=4 宏定义在使用的时候才替换

}

2.条件编译

第一种形式:如果标识符被定义过则编译程序段1,否则编译程序段2。也可以没有#else

 #ifdef 标识符

程序段 1

#else

程序段 2

#endif

第二种:如果标识符没被定义过则编译程序段1,否则编译程序段2。

 #ifndef 标识符

程序段 1

#else

程序段 2

#endif

第三种形式:如常量表达式的值为真(非 0),则对程序段 1 进行编译,否则对程序段 2 进行编译

#if 常量表达式

程序段 1

#else

程序段 2

#endif

#elif 命令意义与 else if 相同

3.文件包含

C语言提供#include 命令来实现文件包含的操作,它实际是宏替换的延伸,有两种格式:

格式 1:

#include <filename>:其中,filename 为要包含的文件名称,用尖括号括起来,也称为头文件,表示预处理到 系统规定的路径中去获得这个文件(即 C 编译系统所提供的并存放在指定的子目录下的头文件)。找到文件后,用文件内容替换该语句。

格式 2:

#include “filename”

其中,filename 为要包含的文件名称。双引号表示预处理应在当前目录中查找文件名为filename 的文件,若没有找到,则按系统指定的路径信息,搜索其他目录。找到文件后,用文件内容替换该语句。

4.#error 预处理指令

作用是,编译程序时,只要遇到 #error 就会生成一个编译错误提示消息,并停止编译。其语法格式为:

#error error-message

宏串 error-message 不用双引号包围。

5.#line

作用是改变行数和文件名称

#line number["filename"]

number从这一条命令的下一行开始生效

6.#pragma 预处理

设定编译器的状态或者是指示编译器完成一些特定的动作

6.1#pragma message(“消息文本”) 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来

6.2#pragma code_seg

格式如:

#pragma code_seg( ["section-name"[,"section-class"] ] )

设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。

6.3#pragma once

只要在头文件的最开始加入这条指令就能够保证头文件被编译一次

6.4#pragma hdrstop 表示预编译头文件到此为止,后面的头文件不进行预编译。

6.5#pragma resource "*.dfm"表示把*.dfm 文件中的资源加入工程。

6.6#pragma warning

6.7#pragma comment(...) 该指令将一个注释记录放入一个对象文件或可执行文件中

6.8#pragma pack

使用指令#pragma pack (n),编译器将按照 n 个字节对齐,n可以取1,2,4,8,16。

使用指令#pragma pack (),编译器将取消自定义字节对齐方式。

//补充的内存对齐部分可参看http://t.csdn.cn/bP4R7

为什么需要内存对齐:为了 提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为 了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。

pragma pack(show)      //显示当前内存对齐的字节数,编辑器默认8字节对齐

内存对齐能提高性能,但有时候会占用更多空间。

7.#运算符

#define SQR(x) printf("The square of "#x" is %d.\n", ((x)*(x)));

再使用:

SQR(8);

则输出的是:

The square of 8 is 64.

8.##运算符

#define XNAME(n) x ## n

如果这样使用宏:

XNAME(8)

则会被展开成这样:

x8

##就是个粘合剂,将前后两部分粘合起来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值