VC预处理命令 第7页
字符化操作符(#@) 将相应的参量置于单引号内,且将其作为字符处理(Microsoft特殊处)
语言符号粘贴操作符(##) 可将语言符号作为实参使用,且将其合并为其它 的语言符号
续表
定义的操作符 简化在某特定宏指令中复合表达式的写法
字符串化操作符(#)
数字符号或“字符串化”操作符(#)将宏参数(扩展后)转化为字符串常量。它只用于带参量的宏。如果它在宏定义中的一个形式参量之前,宏调用传给的实际参量就被括在双括号中,且被看作为一个字符串文字。然后该字符串文字将替换该宏定义中操作符和形参组合的每次出现。
实参的第一个语言符号之前和最后一个语言符号之后的空白被忽略。实参中语言符号之间的所有空白在结果字符串语义中都被看作为一个空格。因此,若实参中的一个注解出现在两个语言符号之间,它将被看作为一个空格。结果字符串文字自动地与任何仅用空格分开的相邻字符串文字连接。
此外,如果一个包含在参量里的字符在用作一个字符串文字(例如,双引号(")或反斜杠(\)字符)时通常需要一个转义序列,必要的转义反斜杠被自动地插入字符之前。下面的例子给出了一个包含字符串化操作符的宏定义和一个调用该宏的main函数:
#define stringer(x) printf(#x "\n")
void main( )
{
stringer(In quotes in the printf function call\n);
stringer("In quotes when printed to the screen"\n);
stringer("This:\" prints an escaped double quote");
}
这种调用在预处理时会被扩展,产生如下代码:
void main()
{
printf("In quotes in the printf function call\n" "\n");
printf("\"In quotes when printed to the screen\"\n" "\n");
printf("\"This;
\\\" prints an escaped double quote \"" "\n");
}
当运行该程序时,每行的屏幕输出如下:
In quotes in the printf function call
"In quotes when printed to the screen"
"This; \" prints an escaped double quotation mark"
Microsoft特殊处
Microsoft C(版本6.0及更早版本)扩展ANSI C的标准,ANSI C扩展在字符串文字和字符常量中出现的宏形式参量不再被支持。依赖于此扩展的代码应该使用字符串化操作符(#)重写。
Microsoft特殊处结束
字符化操作符(#@)
Microsoft特殊处
字符化操作符只可用于宏参量,若宏定义中#@在一个形参前,则实参应被放在单引号中,在宏扩展时作为一个字符处理。例如:
#define makechar(x)
#@x将语句:
a=makechar(b);
扩展为:
a='b';
单引号字符不能用于字符化操作符。
Microsoft特殊处结束语
言符号粘贴操作符(##)
双数字语言符号或“语言符号粘贴”操作符(##),有时称作“合并”操作符,用于类对象宏和类函数宏中。它允许将分开的语言符号加入一个单个语言符号中,因此不能是宏定义的第一个语言符号或最后一个语言符号。
如果一个宏定义中的形参在语言符号粘贴操作符的前后,则形参将立即被未扩展的实参替换。在替换之前不对参量执行宏扩展。
然后,语言符号字符串中语言符号粘贴操作符的每次出现将被删除,其前后的语言符号将被合并。其结果语言符号必须是一个有效的语言符号。若其有效,如果该语言符号代表一个宏名称,则扫描它以发现可能的替换。该标识符表示在替换前程序中己知合并的语言符号的名称。每个语言符号都代表一个在程序中或在编译器命令行中定义的语言符号。
该操作符前后的空白是任意的。
如下例子说明了程序输出中字符串化操作符和语言符号粘贴操作符的用法:#define paster(n) printf("token" #n "=%d",taken##n)
int token9=9;
若一个宏用一个类似于下面的数值参量调用:
paster(9);
宏将生成:
printf("token" "9" "=%d",token9);
它变成为:
printf("token9 = %d", token9 );
________________________________________
宏
对宏扩展的预处理在所有那些不是预处理指令的行(第一个非空白字符不是#的行),以及其指令并未作为条件编译的一部分而忽略的行中进行。“条件编译”指令允许通过检测一个常量表达式或标识符以决定在预处理过程中哪个文本块送入编译器、哪个文本块从源文件中删除,并以此种方式控制一个源文件中某部分的编译。
#define指令通常使用有意义的标识符与常量、关键字、常用语句和表达式关联。表示常量的标识符有时被称作“符号常量”或“显式”常量。表示语句或表达式的常量称为“宏”。在本预处理器文档中,只使用术语“宏”。
当宏的名称在程序源文本或在某些其它预处理器命令的参量中被识别时,它被处理为对该宏的调用。宏名称被宏体的一个拷贝所替换。若该宏接受参量,宏名称后的实参就会替换宏体中的形参。用宏体中处理的拷贝来替换一个宏调用的过程,称为宏调用的“扩展”。
实际的术语中有两种类型的宏。“类对象”宏不带参量,而“类函数”宏可定义为带参量。因此它们的形式和功能都象函数调用,由于宏不生成实际的函数调用,所以有时可用宏替代函数调用使程序运行得更快,(在C++中,inline函数通常是一个好方法),然而,如果不小心的定义和使用宏,也可能造成麻烦。在带参量的宏定义时,你必须使用括号以保持一个表达式中正常的优先级,同时宏也不能正确地处理具有副作用的表达式。有关更多的信息参见“#define指令”中的例子getrandom。
一旦你定义了一个宏,你不能不经取消该宏原有定义,而重新定义它为一个不同的值。但可用正好相同的定义来重定义该宏,因此,一个程序中宏的相同定义可出现多次。
#undef指令用于取消宏的定义。一旦取消该宏的定义,就可重新定义该宏为一个不同的值。#define和#undef两节分别详细讨论了#define和#undef指令。
宏和C++
C++提供了一些新的功能。其中有些功能替代了原来由ANSI C所提供的功能。这些新的功能增强了类型安全性和该语言的可预测性:
* 在C++中,以const说明的对象可用于常量表达式中,这使程序说明有类型和值信息的常量,以及能被调试器逐个字符检查的枚举值的常量。使用预处理器指令#define定义常量并不精确。除非在程序中找到一个带地址的表达式,否则一个const对象将不分配任何存储。
* C++联编函数替代了函数类型宏,相对于宏来说使用联编函数的优势在于:
* 类型安全性。联编函数和一般函数一样需进行相同的类型检测,宏无类型安全性检测。
* 纠正具有副作用的参量处理。联编函数在进入函数体之前对参量的表达式求值。因此,一个有副作用的表达式将是安全的。
对于联编函数的更多信息参见inline、_ _inline节。为了向下兼容,Microsoft C++保留了所有在ANSI C和更早C++规格中的预处理器功能。
预定义宏
编译器可识别辣种预定义的ANSI C宏(参见表1.1),而Microsoft C++实现提供更多的预定义宏(参见表1.2)。这些宏不带参量,但不能被重定义。它们的值(除__LINE_ _和_ _FILE_ _外)必须是经过编译的常量。下面列出的一些预定义宏须用多个值来定义,它们的值可在Visual C++开发环境中选择相应的菜单选项来设置或采用命令行开关。更多的信息参见下表。
表1.1 ANSI 预定义宏
宏 说明
__DATE _ _当前源文件的编译日期。日期是格式为Mmm dd yyyy的字符串文字。月份名称Mmm与在TIME.H中说明的库函数asctime产生的日期一样
上一页 [1] [2] [3] [4] [5] [6] [7] [8] 下一页
VC预处理命令 第7页下载如图片无法显示或论文不完整,请联系qq752018766