VC中有一类宏并不是由用户用#define语句定义的,而是编译器本身就能够识别它们。当编译器遇到__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__宏。

C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量 通过替换后在其左右各加上一个双引号。

##被称为连接符(concatenator),用来将两个Token连接为一个Token。注意这里连接的对象是Token就行,而不一定 是宏的变量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组,并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。