预处理器

本文深入探讨C语言预处理器的功能和用法,包括预定义符号、宏定义、条件编译、文件包含等关键特性,并提供了丰富的示例代码。

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

《C与指针》读书笔记
1. 预定义符号
符号 样例值 含义
__FILE__“name.c” 进行编译的源文件名
__LINE__25 文件当前的行号
__DATE__“Jan 31 1997” 文件被编译的日期
__TIME__“18:04:30” 文件被编译的时间
__STDC__1如果编译器遵循ANSI C,其值就为1,否则未定义。
2 #define
#define name stuff
有了这条指令以后,每当有符号name出现在这条指令后面时,预处理器就会把它替换成staff。
2.1 宏
#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏或定义宏。下面是宏的声明方式:
#define name(parameter-list) stuff
所有用于对数值表达式进行求值的宏定义都应该加上括号,避免在使用宏时,由于参数中的操作符临近的操作符之间不可预料的相互作用。
2.2 #define替换
在程序中扩展#define定义符号和宏时,需要涉及几个步骤。
1.在调用宏时,首先对参数进行检查,看看是否包含了任何由#define定义的符号。如果是,它们首先被替换。
2.替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被它们的值所替代。
3.最后,再次对结果文本进行扫描,看看它是否包含了任何由#define定义的符号。如果是,就重复上述处理过程。
宏不可以递归。
如果想把宏参数插入到字符串常量中,可以使用两种技巧。
(1)临近字符串自动连接
#define PRINT(FORMAT,VALUE) printf("The value is " FORMAT "\n",value)
PRINT("%d",x + 3);
(2)#argument
#define PRINT(FORMAT,VALUE)\
printf("The value of " #VALUE)\
" is " FORMAT "\n",VALUE)
PRINT("%d",x + 3);
它将产生输出: The value of x + 3 is 25
##符号把位于它两边的符号连接成一个符号。
#define ADD_TO_SUM(sum_number,value)\
sum##sum_number += value
ADD_TO_SUM(5,25);
最后一天语句把值25加到变量sum5。
2.3 宏与函数
宏非常频繁地用于执行简单的计算。
#define MAX(a,b) ((a) > (b) ? (a) : (b))
用于调用和从函数返回的代码很可能比实际执行这个小型计算工作的代码更大,所以使用宏比使用函数在程序的规模和速度方面更胜一筹。另一个方面的优点:宏与类型无关。
除非宏非常短,否则使用宏可能会大幅度增加程序的长度。
2.4 带副作用的宏参数
当宏参数在宏定义中出现的次数抽过一次时,如果这个参数具有副作用,那么当你使用这个宏时就可能出现危险。
有副作用的参数比如x++。它增加了x的值。
#define MAX(a,b) ((a) > (b) ? (a) : (b))
x = 5;
y = 8;
z = MAX(x++,y++);
最后一个语句宏替换之后:
z = (x++,y++) ((x++) > (y++) ? (x++) : (y++));
较小的值增值一次,较大的值增值了两次!
另外一个有副作用的参数:getchar()。
#define EVENPARITY(ch)\
((count_one_bits(ch) & 1) ? \
(ch)|PARITYBIT :(ch))
当宏函数被这样调用时,是危险的。
ch = EVENPARITY(getchar());
它实际上读入了两个字符。
2.5 命名约定
一个常见的约定就是把宏名字全部大写。
2.6 #undef
这条预处理指令用于移除一个宏定义。
#undef name
2.7 命令行定义
int array[ARRAY_SIZE];
在编译程序时,ARRAY_SIZE的值可以在命令行指定。
在UNIX编译器中,-D选项可以指定一个宏定义的值。
-Dname=stuff
如下:
cc -DARRAY_SIZE=100 prog.c
3 条件编译
#if constant-expression
statements
#endif
其中,constant-expression(常量表达式)由处理器进行求值。如果它的值是非零值,那么statements部分就被正常编译,否则删除。
#if指令有可选的#elif和#else子句。完整的语法如下:
#if constant-expression
statements
#elif constant-expression
other statements
#else constant-expression
other statements
#endif
3.1 是否被定义
#if defined(symbol)
#ifdef symbol

#if !defined(symbol)
#ifndef symbol
3.2 嵌套指令
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_of_option1();
#endif
#ifdef OPTION2
unix_version_of_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_of_option2();
#endif
#endif
4 文件包含
4.1 函数库文件包含
#include <filename>
4.2 本地文件包含
#include "filename"
5 其他指令
(1)#error
#error指令允许你生成错误信息
(2)#line
#line number "string"
它通知预处理器number是下一行输入的行号。这条指令将修改__LINE__符号的值,如果加上可选部分"string",它将修改__FILE__的值。
(3)#progma
#progma指令用于支持因编译器而异的特性。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值