分类: C/C++
2007-01-09 15:49:42
#ifndef | 测试一个宏是否未定义 |
#ifdef | 测试一个宏是否已定义 |
#if | 类似于if ,但可以用于测试关于宏的条件表达式 |
#else | 类似于else ,但可以用于测试关于宏的条件表达式 |
#elif | 类似于else if ,用于与#if构建类似“if……else if……”结构的语句 |
#endif | 凡是使用了上面任何一种方案,结尾一定要使用该语句 |
#undef | 取消一个宏定义 |
有关#define的宏替换:
壹·接受可变参数的宏
事实上,利用#define 我们完全可以制作一个参数可变的宏(1个?2个?3个?没有参数?都没问题)
比如:
#define test(...) printf("TEST: "__VA_ARGS__);
main() //上面括号中的“...”就是“...”我可完全没省略什么
{int a=567;
// 语句 |
// 对应的输出 |
test("\n"); | TEST: <回车> |
test("%i \n",a); | TEST: 567 <回车> |
test("AS"); | TEST: AS |
....}
表面上看起来,这是令人费解的,其实这包含了两个原理,明白了他们,就明白这个现象了。
原理:
<1> 宏(在这里指的就是test)在函数体中被引用时,它的参数会被原方不动地端去替掉宏定义中__VA_ARGS__的位置。
<2> C编译器总是试图把两个相邻的字符串常量合并。
比如:"ABC" 与 "DEF" 在某种场合被写成
…… "ABC" "DEF" ……
时,C编译器会自动把处于内部的那对双引号抵消(这就是合并的过程),它会被识别为
…… "ABCDEF" ……
现在,再回头看看例子中的语句和对应的输出,就能明白了吧!
注:对于括号中的那三个点,经测试无误,但原理不明。(据说是史前文明遗留的产物)
贰·#控制符
想来想去,愚者还是要把这个方案也补充一下,与前者相比,这个更为自动化,但很大程度上,自由度也会多受一些限制。
宏定义时,在后面的公式中,如果在参数前面加#号,当调用该宏时,参数会被自动声明为字符串常量并自动加上双引号之后去替换公式中#参数所在的位置(这句话很长是吧?愚者之所以没有使用逗号,是因为"之后"这个字眼,就是说,宏所接收的内容并非只有字符串,还有那个变量),比如:
#define echo(xxx) printf(#xxx"=%i \n",xxx); // 看到了吧?被接收的还有变量本身
main()
{int ani=567;
echo(ani); // 这会产生什么样的结果呢?
这条语句会被替换为 printf("ani""=%i \n",ani);
也就是(遵循合并字符串常量的原则) printf("ani=%i \n",ani);
对比:
在此,愚者不得不对它们进行一下对比,这也正是愚者把这篇文章写到这么长的真正目的所在。
就这两种情形而言,这是两个极端的情况,所谓
鱼(便捷)与熊掌(功能)不可兼得
这恐怕是造物主创世时留下的方案 (如果你非说是AT&T,愚者也没有办法)
形象点说,第一个方案比较像是“手动照相机”,而第二个更像是“自动照相机”。
(即使它们不能用来照相)
手动者具有比较广泛的功能,它可以利用左边的双引号被抵消的空余,渗入到公式的格式控制部分,进行修改——这看起来的确有那么一点晦涩。
自动者由于被自动加上了双引号,使我们免去了自己输入的麻烦(大约要浪费0.2秒),同时它利用带参数宏定义的基本原理使得这个方案看起来更加便捷——但如果要输出的还有字符串或是符点数据,那怎么办?要我们声明三个几乎一模一样的宏?——那种情况还是手动者比较便捷吧?
好了,这篇文章到此为止,再往下加东西,读起来会令人生厌的。