宏编译的一个问题
本问题涉及一些宏的高级用法:字符串化及不定参数宏. 问题在下述测试代码中,请指点.谢谢.
[I][COLOR=#008800]01 [/COLOR][/I] [COLOR=#008080]#include <stdio.h>[/COLOR]
[I][COLOR=#008800]02 [/COLOR][/I] [COLOR=#008080]#include <string.h>[/COLOR]
[I][COLOR=#008800]03 [/COLOR][/I]
[I][COLOR=#008800]04 [/COLOR][/I] [I][COLOR=#008800]/* 除了PR0外,其它宏都有一个ID参数 */[/COLOR][/I]
[COLOR=#f810b0]05 [/COLOR] [COLOR=#008080]#define PR0(str) printf("PR0 Message: %s\n", str)[/COLOR]
[I][COLOR=#008800]06 [/COLOR][/I] [COLOR=#008080]#define PR1(id, ...) printf("PR1 Message" #id ": " __VA_ARGS__)[/COLOR]
[I][COLOR=#008800]07 [/COLOR][/I] [COLOR=#008080]#define PR2(id, str, i, j) printf("PR2 Message" #id ": %s=%d\n", str, i+j)[/COLOR]
[I][COLOR=#008800]08 [/COLOR][/I]
[I][COLOR=#008800]09 [/COLOR][/I] [I][COLOR=#008800]/* 本宏的目的是调用上述各宏,所以需要对PR0区别对待--如果是PR0宏, 调用时不带ID参数.[/COLOR][/I]
[COLOR=#f810b0]10 [/COLOR] [I][COLOR=#008800] * 问题是: 除非将16-20行注释掉,否则无法通过编译, 为什么?[/COLOR][/I]
[I][COLOR=#008800]11 [/COLOR][/I] [I][COLOR=#008800] * 注释掉的这几行代码看起来并无问题,因为下面的测试宏cmp_str 和 call_macro 编译/运行都正常[/COLOR][/I]
[I][COLOR=#008800]12 [/COLOR][/I] [I][COLOR=#008800] */[/COLOR][/I]
[I][COLOR=#008800]13 [/COLOR][/I] [COLOR=#008080]#define CALL_MACRO(macro, id, ...) \[/COLOR]
[I][COLOR=#008800]14 [/COLOR][/I] [COLOR=#008080]{ \[/COLOR]
[COLOR=#f810b0]15 [/COLOR] [COLOR=#008080] printf("Test " #macro "...\n"); \[/COLOR]
[I][COLOR=#008800]16 [/COLOR][/I] [I][COLOR=#008800]/* if (0 == strcmp(#macro, "PR0")) \[/COLOR][/I]
[I][COLOR=#008800]17 [/COLOR][/I] [I][COLOR=#008800] { \[/COLOR][/I]
[I][COLOR=#008800]18 [/COLOR][/I] [I][COLOR=#008800] macro(__VA_ARGS__); \[/COLOR][/I]
[I][COLOR=#008800]19 [/COLOR][/I] [I][COLOR=#008800] } \[/COLOR][/I]
[COLOR=#f810b0]20 [/COLOR] [I][COLOR=#008800] else \[/COLOR][/I]
[I][COLOR=#008800]21 [/COLOR][/I] [I][COLOR=#008800]*/[/COLOR][/I][COLOR=#008080] if (1) \[/COLOR]
[I][COLOR=#008800]22 [/COLOR][/I] [COLOR=#008080] { \[/COLOR]
[I][COLOR=#008800]23 [/COLOR][/I] [COLOR=#008080] macro(id, __VA_ARGS__); \[/COLOR]
[I][COLOR=#008800]24 [/COLOR][/I] [COLOR=#008080] } \[/COLOR]
[COLOR=#f810b0]25 [/COLOR] [COLOR=#008080]}[/COLOR]
[I][COLOR=#008800]26 [/COLOR][/I]
[I][COLOR=#008800]27 [/COLOR][/I] [I][COLOR=#008800]/* verify the stringizing function of macro */[/COLOR][/I]
[I][COLOR=#008800]28 [/COLOR][/I] [COLOR=#008080]#define cmp_str(str) \[/COLOR]
[I][COLOR=#008800]29 [/COLOR][/I] [COLOR=#008080]{ \[/COLOR]
[COLOR=#f810b0]30 [/COLOR] [COLOR=#008080] if (0 == strcmp(#str, "hi")) \[/COLOR]
[I][COLOR=#008800]31 [/COLOR][/I] [COLOR=#008080] printf("Hello!\n"); \[/COLOR]
[I][COLOR=#008800]32 [/COLOR][/I] [COLOR=#008080] else \[/COLOR]
[I][COLOR=#008800]33 [/COLOR][/I] [COLOR=#008080] printf("Bad passcode!\n"); \[/COLOR]
[I][COLOR=#008800]34 [/COLOR][/I] [COLOR=#008080]}[/COLOR]
[COLOR=#f810b0]35 [/COLOR]
[I][COLOR=#008800]36 [/COLOR][/I] [COLOR=#008080]#define call_macro(macro, id, ...) \[/COLOR]
[I][COLOR=#008800]37 [/COLOR][/I] [COLOR=#008080]{ \[/COLOR]
[I][COLOR=#008800]38 [/COLOR][/I] [COLOR=#008080] macro(__VA_ARGS__); \[/COLOR]
[I][COLOR=#008800]39 [/COLOR][/I] [COLOR=#008080]}[/COLOR]
[COLOR=#f810b0]40 [/COLOR]
[I][COLOR=#008800]41 [/COLOR][/I] [B][COLOR=#000080]int[/COLOR][/B] [COLOR=#000000]main[/COLOR]()
[I][COLOR=#008800]42 [/COLOR][/I] [COLOR=#000000]{[/COLOR]
[I][COLOR=#008800]43 [/COLOR][/I] [COLOR=#000000]CALL_MACRO[/COLOR]([COLOR=#000000]PR1[/COLOR][COLOR=#000000],[/COLOR] [COLOR=#0000ff]1[/COLOR][COLOR=#000000],[/COLOR] [COLOR=#0000ff]"hello %s[/COLOR][COLOR=#0000ff]\n[/COLOR][COLOR=#0000ff]"[/COLOR][COLOR=#000000],[/COLOR] [COLOR=#0000ff]"world"[/COLOR])
[I][COLOR=#008800]44 [/COLOR][/I] [COLOR=#000000]CALL_MACRO[/COLOR]([COLOR=#000000]PR2[/COLOR][COLOR=#000000],[/COLOR] [COLOR=#0000ff]2[/COLOR][COLOR=#000000],[/COLOR] [COLOR=#0000ff]"total"[/COLOR][COLOR=#000000],[/COLOR] [COLOR=#0000ff]3[/COLOR][COLOR=#000000],[/COLOR] [COLOR=#0000ff]4[/COLOR])
[COLOR=#f810b0]45 [/COLOR] [I][COLOR=#008800]// CALL_MACRO(PR0, -1, "hi")[/COLOR][/I]
[I][COLOR=#008800]46 [/COLOR][/I]
[I][COLOR=#008800]47 [/COLOR][/I] [COLOR=#000000]cmp_str[/COLOR]([COLOR=#000000]hi[/COLOR])
[I][COLOR=#008800]48 [/COLOR][/I] [COLOR=#000000]cmp_str[/COLOR]([COLOR=#000000]hello[/COLOR])
[I][COLOR=#008800]49 [/COLOR][/I] [COLOR=#000000]call_macro[/COLOR]([COLOR=#000000]PR0[/COLOR][COLOR=#000000],[/COLOR] [COLOR=#000000]-[/COLOR][COLOR=#0000ff]1[/COLOR][COLOR=#000000],[/COLOR] [COLOR=#0000ff]"hello"[/COLOR])
[COLOR=#f810b0]50 [/COLOR]
[I][COLOR=#008800]51 [/COLOR][/I] [B][COLOR=#000080]return[/COLOR][/B] [COLOR=#0000ff]0[/COLOR];
[I][COLOR=#008800]52 [/COLOR][/I] [COLOR=#000000]}[/COLOR]
[/FONT]
保留第16-20行代码时的编译错误如下:
test> gcc mm.c
mm.c:44:37: macro "PR2" requires 4 arguments, but only 3 given
mm.c: In function `main':
mm.c:44: error: `PR2' undeclared (first use in this function)
mm.c:44: error: (Each undeclared identifier is reported only once
mm.c:44: error: for each function it appears in.)
另: 用gcc -E进行宏展开时代码没有问题.