VC预处理命令

VC预处理命令
预处理器是一种处理源文件文本的文本处理器,它是翻译起始阶段的一个组成部分。
预处理器并不在语法上分析处理源文本,但出于定位宏调用的目的,它将源文本分开语言符号。虽然编译器一般在初次编译时启动预处理器,但预处理器也可以不经编译,单独地处理文本。
Microsoft特殊处
用/E或/EP编译器选项进行预处理之后,你可以得到一个源代码的列表。在多数情况下,启动预处理器和输出结果文本到输出设备,这两种选项都是控制台指令,这两种选项的区别在于/E包括了#line指令,/EP没有这些指令。
Microsoft特殊处结束
________________________________________特殊术语
在本书中,名词“参量”指的是传送给一个函数的实体。有时候,它用“actual”或“formal”修饰,它们分别用于表示函数调用时的参量表达式和在函数定义时的参量说明。名词“变量”指的是一种简单的C类型数据对象,名词“对象”指的是C++对象和变量;它是一个含义广泛的名词。
________________________________________翻译阶段
C和C++程序由一个或多个源文件组成,它们都包含了程序的某些文本,一个不包含代码部分的源文件和它的包含文件(用#indude预处理器指令包含的文件),若被条件编译指令(比如#if)调用,则称其为一个“转换单元”。
源文件可被翻译多次,翻译过去的文件事实上是很正常的。已经翻译了的翻译单元可保存在单独的对象文件或对象代码库里,这些单个的转换单元可被连接形成一个可执行文件或动态链接库(DLL)。
转换单元可采用下列形式通信:
* 调用具有外部连接的函数。
* 调用具有外部连接的类成员函数。
* 直接更改具有外部连接的对象。
* 文件的直接更改。
* 内部外理通信(仅限于基于Microsoft Windows的应用程序)。以下是编译器翻译文件的各个阶段:
字符映射
源文件中的字符被映射为内部源代码的形式。此阶段三字母序列被转换为单字符的内部表现形式。
行拼接
在此阶段,源文件中所有以反斜杠(\)结尾且其后紧跟一换行符的行,将与下一行连接,从而由物理行生成逻辑行。所有非空源文件结束于一个前面没有反斜杠的换行符。
语言符号化
此阶段源文件被分为预处理语言符号和空白字符。源文件中每个注释被用一个空白字符代替。换行符被保留。
预处理
此阶段执行预处理指令并将宏扩展至源文件,#i nclude语句调用对所有包括文本启动前面三个翻译步骤开头的翻译过程。
字符集映射
所有的源字符集成员和转义序列将转换为执行字符集中的等价形式,对于Microsoft C和C++来说,源字符集和执行字符集都是ASCII码。
字符串合并
所有相邻的字符串和宽字符文字都将被合并。例如:“String”“concatenation”合并为“Stringconcatenation”。
翻译
所有的语言符号将按语法和语义规则进行分析;这些语言符号被转换为目标代码。
链接
此阶段所有的外部引用被分解以生成一个可执行程序或一个动态链接库。
编译器在翻译过程中遇到语法错误时,将发出一个警告或错误信息。
链接器分解所有的外部引用,并把一个或多个分开处理的转换单元和标准库联接起来,以生成一个可执行程序或动态链接库(DLL)。
________________________________________
预处理器指令
预处理器指令如#define和#ifdef,一般被用在不同的运行环境下,使源程序易于更改和编译。源文件中的指令指示预处理器执行特有的行为。例如,预处理器可替换文本中的语言符号,将其它的文件内容插入源文件中,或移走文本的一部分以抑制文件中某部分的编译。预处理器行在宏扩展之前被识别且执行。不过,如果宏扩展看起来象一个预处理器指令,该命令将不能被预处理器识别。
除转义序列之外,预处理器语句采用与源文件语句相同的字符集。在预处理器语句中的字符集和可执行程序的字符集是一样的。预处理器也可识别负字符值。预处理器可识别如下指令:
#define #error #import #undef
#elif #if #i nclude
#else #ifdef #line
#endif #ifndef #pragma
数字符号(#)是包含预处理器指令的行中的第一个非空白字符。空白字符可出现在数字符号和指令的第一个字母之间。某些指令包含参量和值。指令之后的任何文本(除作为指令一部分的参量或值之外)必须放在单行注释分界符(//)之后或注释分界符(/* */)之间。
预处理器指令可出现在源文件的任何地方,但它们仅用于源文件的剩余部分。
#define指令
可以用#define指令给程序中的常量取一个有意义的名称,其语法的两种形式如下:
语法
#define 标识符 语言符号字符串
opt#define 标识符[(标识符opt,...,标识符opt)]语言符号字符串opt
#define指令用语言符号字符串替换源文件中一个标识符的所有出现,标识符仅在它形成一个语言符号时被替换(参见“Microsoft Visual C++ 6.0参考库”的“Microsoft Visual C++ 6.0语言参考手册”卷的第1章“词法规定”中的“语言符号”)。例如,若标识符出现在一个注释、一个字符串或作为一个长标识符的一部分之中,它就不被替换。
一个不带语言符号字符串的#define指令将移走源文件中每次标识符的出现。标识符保留其定义且能用#defined和#ifdef测试。
语言符号字符串参量由一系列语言符号组成,如关键字、常量或完整的语句。一个或多个空白字符可将语言符号字符串和标识符分开。空白字符不会被认为是被替换文本的一部分,文本最后语言符号之后的空白也不会认为是替换文本的一部分。
形式参数名称出现在语言符号字符串中以标志出实际值被替换的位置,每个参数名称可在语言符号字符串中出现多次,且可以以任何次序出现。调用时参量的数目必须与宏定义的参数数目相匹配。圆括号的自由运用可确保正确地说明复杂的实际参量。
用第二种语法形式可创建类似函数的宏。这种形式接受一个用圆括号括起的可选参数表。在最初定义之后引用该标识符,可以使用实际参量替代形式参数的语言符号字符串参量的形式,来替换标识符(标识符opt,...,标识符opt)的每次出现。
表中的形式参数必须用逗号隔开。该表中的每个名称都必须是唯一的,且此参量表必须包括在圆括号中,标识符和左边的圆括号之间不能有空格。对于占用多行的长指令可使用行连接,把反斜杠(\)放在换行符前。形式参数名称的范围延伸到结束语言符号字符串的换行符。
当一个宏以第二种语法形式定义时,参量表后的文本实例就构成一个宏调用。在源文件中,一个标识符实例后的实际参量必须与宏定义的相应形式参数匹配。每个语言符号字符串之前无字符串化(#)、字符化(#@)或语言符号粘贴(##)操作符,或其后无##操作符的形式参量,都被相应的实际参量所替换。在指令替换形式参数之前,实际参量中的任何宏都将被扩展(本章之后的“预处理器操作符”中将介绍这些操作符)。
以下带参量宏的例子说明了#define语法的第二种形式:
//定义光标行的宏
#define CURSOR(top,bottom) ((top) << 8) | bottom))
//获取指定范围中的一个随机整数的宏
#define getrandom(min,max) \
((rand()%(int)(((max)+1)-(min)))+(min))
有副作用的参量有时会导致宏产生不希望的结果。一个给定的形式参量在语言符号字符串中可能出现多次。如果该形式参数被一个有副作用的表达式所替换,则该表达式及其副作用,可能被求值多次(参见本章后面“语言符号粘贴操作符##”中的例子)281

[1] [2] [3] [4] [5] [6] [7] [8] 下一页

  • 上一篇文章:
  • 下一篇文章:
  • Copyright © 2007-2012 www.chuibin.com 六维论文网 版权所有