在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。其格式一般为
#Pragma Para
其中Para 为参数,下面来看一些常用的参数。
message 参数。 Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:
#Pragma message(“消息文本”)
当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法
#ifdef _X86
#Pragma message(“_X86 macro activated!”)
#endif
当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_X86 macro activated!”。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。
另一个使用得比较多的pragma参数是code_seg.格式如:
#pragma code_seg( ["section-name"[,"section-class"] ] )
它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。
最后一个比较常用的就是上面所说的#pragma once 指令了。
VC预定义的宏
在VC中有一类宏并不是由用户用#define语句定义的,而是编译器本身就能够识别它们。这些宏的作用也是相当大的。让我们来看第一个,也是MFC中使用得最频繁的一个:__FILE__ .
当编译器遇到这个宏时就把它展开成当前被编译文件的文件名。好了,我们马上就可以想到可以用它来做什么,当应用程序发生错误时,我们可以报告这个错误发生的程序代码在哪个文件里,比方在文件test.cpp中有这样的代码:
try
{
char * p=new(char[10]);
}
catch(CException *e )
{
TRACE(“ there is an error in file: %s\n”,__FILE__);
}
在程序运行的时候,如果内存分配出现了错误,那么在调试窗口中会出现there is an error in file: test.cpp 这句话,当然,我们还可以把这个错误信息显示在别的地方。
如果我们还能够记录错误发生在哪一行就好了,幸运的是,与__FILE__宏定义一样,还有一个宏记录了当前代码所在的行数,这个宏是__LINE__.使用上面的两个宏,我们可以写出一个类似于VC提供的ASSERT语句。下面是方法
#define MyAssert(x) \
if(!(x)) \
MessageBox(__FILE__,__LINE__,NULL,MB_OK);
我们在应用程序中可以象使用ASSERT语句一样使用它,在错误发生时,它会弹出一个对话框,其标题和内容告诉了我们错误发生的文件和代码行号,方便我们的调试,这对于不能使用ASSERT语句的项目来说是非常有用的。
除了这两个宏以外,还有记录编译时间的__TIME__,记录日期的__DATE__,以及记录文件修改时间的__TIMESTAMP__宏。
使用这些预定义的宏,我们几乎可以生成和VC能够生成的一样完整的源代码信息报表。
结论
翻开MFC和Linux的源代码,宏定义几乎占据了半边天,消息映射,队列操作,平台移植,版本管理,甚至内核模块的拆卸安装都用宏定义完成。毫不夸张的说,有些文件甚至就只能看见宏定义。所以学习宏定义,熟练的使用宏定义对于学习C语言乃至VC都是非常关键的