【C】C语言预处理器的几个命令

C语言预处理器是个简单的的宏处理器,预处理器用特殊的命令行控制,这些命令行以符号#开头,不包含预处理器命令的行称为源程序文本行。预处理器通常从源文件中删除所有预处理器命令行,并按预处理器命令指示对源文件进行其它转换,然后,得到的经过预处理的源文本成为有效C语言程序。

下面是常见的预处理器命令:
#define——定义预处理器宏,如果是函数式宏定义,左括号与宏名之间不能有空格,所有参数及整个宏替换最好分别放在圆括号里,参数可以是可变参数列表,以三个点...表示,用内建变量__VA_ARGS__替换,传人的参数包含自赠自减运算符时会带来副作用,还需注意的是宏定义结束处的分隔符,可以使用反斜杠\进行续行。
#undef——取消预处理器宏定义。
#include——插入另一源文件中的文本。
#if——根据常量表达式值有条件地包括一些文本。
#ifdef——根据是否定义宏有条件地包括一些文本。
#ifndef——根据与#define相反的测试有条件地包括一些文本。
#else——上述#if、#ifdef、#ifndef或#elif测试失败时包括一些文本。
#endif——终止条件文本。
#line——提供编译器消息的行号。
#elif——上述#if、#ifdef、#ifndef或#elif测试失败时根据另一常量表达式值包括一些文本。
defined——预处理器函数,在一个名称定义为预处理器宏时为1,否则为0,在#if与#elif中使用。
#运算符——将宏参数换成包含参数值的字符串常量。
##运算符——从两个相邻记号生成一个记号。
#pragma——对编译器指定相关消息,效果同C99增加的_Pragma运算符。#pragma可以单独放在一行,其预处理器记号不随宏扩展,而_Pragma可以放在其它表达式中间,可以通过宏扩展产生。
#error——将编译错误换成指定消息。

定义语句上下文中使用的函数式宏比较复杂,下列宏交换两个参数x与y中的值,假设其数值类型可以换算为unsigned long,并且换算回元类型后不发生改变,且不涉及_temp标识符。
#define swap(x, y) { unsigned long _temp = x; x = y; y = temp; }
问题是,我们习惯于在swap之后放一个分号。
if (x > y) swap(x, y);
else x = y;
就好像swap是个实际函数一样,这会出错,因为扩展后的语句包含多余的分号,我们把扩展语句放在另一行,可以更清楚地说明这个问题。
if (x > y) { unsigned long _temp = x; x = y; y = temp; }
;
else x = y;
要避免这个问题,一个聪明的办法是将宏体定义为do-while语句,这样可以吸收多余的分号。
#define swap(x, y) \
do { unsigned long _temp = x; x = y; y = temp; } while (0)

标准C语言预处理器要求定义某些对象式宏,每个预定义宏的名称以两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程人员重新定义。

下面是常见的预定义宏——
__LINE__:当前源程序行的行号,表示为十进制整形常量。
__FILE__:当前源文件名,表示为字符串型常量。
__DATE__:转换的日历日期,表示为"MM dd yyyy"形式的字符串型常量,MM是由asctime产生的。
__TIME__:转换的时间,表示为"hh:mm:ss"形式的字符串型常量,是由asctime产生的。
__STDC__:编译器为ISO兼容实现时为十进制整形常量1。__STDC__是否在C++环境中定义取决于实现。标准C语言与C++有一定差别,因此不知道是否要定义__STDC__。
__STDC_VERSION__:如果实现符合C89增补1,则这个宏的值为199409L;如果实现符合C99,则这个宏的值为199901L;否则数值是未定义。
__STDC_HOSTED__:(C99)实现为宿主实现时为1,实现为独立实现时为0。
__STDC_IEC_559__:(C99)浮点数实现符合IEC 60559标准时定义为1,否则数值是未定义。
__STDC_IEC_559_COMPLEX__:(C99)复数运算实现符合IEC 60559标准时定义为1,否则数值是未定义。
__STDC_ISO_10646__:(C99)定义为长整型常量,yyyymmL表示wchar_t值符合ISO 10646标准及其指定年月的修订补充,否则数值未定义。

另外,实现还经常定义其它宏用于传递环境消息,如进行程序编译工作的计算机类型。具体定义哪些宏是由实现决定的,但UNIX实现习惯上预定义unix。与内置宏不同的是,这些宏可以取消定义。标准C语言要求特定实现的宏名以下划线开头,加上大写字母或另一个下划线(unix宏不符合这个要求)。

C99定义了几个标准杂注pragma,FF_CONTRACT、FENV_ACCESS和CX_LIMITED_RANGE,它们取一个参数作为开关:ON、OFF、DEFAULT。

预定义标识符尽管不是关键字,但C99中引入了预定义标识符的概念,并定义了一个预定义标识符:__func__。与预定义宏不同的是,预定义标识符可以采用正常的标识符作用域规则,和关键字一样,预定义标识符不能由编程人员定义。

C++使用C89预处理器,因此C语言与C++之间差别不大。宏__cplusplus是C++实现中预定义的,可以在C和C++环境中的源文件中使用。这个名称不符合预定义宏的标准C语言拼写规则,但与现有C++实现兼容。在标准C语言中,它的值为199711L之类的版本号。


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值