C 语言宏的高级应用 关 于 # 和 ##在 C 语 言的 宏 中 , #的 功能 是 将其 后 面 的宏 参数 进 行字符 串 化 操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号。比如下面代码中的宏: #define WARN_IF(EXP) \ do{ if (EXP) \ fprintf(stderr, "Warning: " #EXP "\n"); } \ while(0) 那么实际使用中会出现下面所示的替换过程: WARN_IF (divider == 0); 被替换为 do { if (divider == 0) fprintf(stderr, "Warning" "divider == 0" "\n"); } while(0); 这样每次 divider(除数)为 0 的时候便会在标准错误流上输出一个提示信息。 而##被称为连接符(concatenator),用来将两个 Token 连接为一个 Token。注意这里连接的对象是 Token 就行,而不一定是宏的变量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组,并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。那么下面的代码就非常实用: struct command { char * name; void (*function) (void); }; #define COMMAND(NAME) { NAME, NAME ## _command } // 然后你就用一些预先定义好的命令来方便的初始化一个 command 结构的数组了: struct command commands[] = { COMMAND(quit), COMMAND(help), ... } COMMAND 宏在这里充当一个代码生成器的作用,这样可以在一定程度上减少代码密度,间接地也可以减少不留心所造成的错误。我们还可以 n 个##符号连接 n+1 个 Token,这个特性也是#符号所不具备的。比如: #define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d typedef struct _record_type LINK_MULTIPLE(name,company,position,salary); // 这里这个语句将展开为: // typedef struct _record_type name_company_position_salary; 关于...的使用 ...在 C 宏中称为 Variadic Macro,也就是变参宏。比如: #define my printf(templt,...) fprintf(stderr,templt,__VA_ARGS__) // 或者 #define my printf(templt,args...) fprintf(stderr,templt,args) 第一个宏中由于没有对变参起名,我们用默认的宏__VA_ARGS__来替代它。第二个宏中,我们显式地命名变参为 args,那么我们在宏定义中就可以用 args 来代指变参了。同 C 语言的 stdcall 一样,变参必须作为参数表的最有一项...