在C宏中模拟范围

时间:2013-12-07 22:48:10

标签: c macros scope

我有以下宏来打印出整数数组的内容以用于调试目的:

#define PRINT_ARRAY(ary, num)        \
    int ai = 0;                      \
    printf("{");                     \
    for(ai=0; ai < num; ++ai) {      \
        printf("%d", ary[ai]);       \
        if(ai < num-1) printf(", "); \
    }                                \
    printf("}\n");

我遇到的问题是,当我多次使用它时,一些编译器会抱怨我正在重新定义ai

有没有办法让每次调用宏时标识符都不同?我可以提出一个名称冲突变化非常小的命名方案,但我想让它自动化。

我知道我可以使用一个函数,但我仍然很好奇,因为我想知道是否有办法用宏来做这个。

3 个答案:

答案 0 :(得分:6)

为什么不使用经典的do-while技巧?例如:

#define FOO(EXPR) \
  do { \
    (EXPR); \
  } while(0)

答案 1 :(得分:2)

你可以把它放在它自己的范围内,例如用{}

围绕它

像这样:

#define PRINT_ARRAY(ary, num)        \
{                                \
    int ai = 0;                      \
    printf("{");                     \
    for(ai=0; ai < (num); ++ai) {      \
        printf("%d", ary[ai]);       \
        if(ai < (num)-1) printf(", "); \
    }                                \
    printf("}\n");                   \
}

我还在num参数周围添加了parantheses,因此您可以使用复杂的表达式而不会产生奇怪的副作用。

WRT到您的标识符命名:

您可以使用宏扩展来使用参数更改名称,但由于我知道所有c预处理器中都没有计数器或循环结构,因此我认为不可能在每个用户之后自动更改标识符。另一种方法是让宏每次重新定义自己,但是这也是不可能的。

编辑:

正如已经指出的那样(感谢Aaron McDaid,也看到他提出的链接:https://stackoverflow.com/a/1067238/146041),你应该在代码周围使用do { } while(0)构造,这样你的宏会成为:

#define PRINT_ARRAY(ary, num)        \
do {                                \
    int ai = 0;                      \
    printf("{");                     \
    for(ai=0; ai < (num); ++ai) {      \
        printf("%d", ary[ai]);       \
        if(ai < (num)-1) printf(", "); \
    }                                \
    printf("}\n");                   \
} while(0)

答案 2 :(得分:2)

如果您的C符合C99,请将ai的声明放在for循环的标题中。您还应该使用do / while(0)

包围代码
#define PRINT_ARRAY(ary, num)        \
    do {printf("{");                     \
    for(int ai=0; ai < num; ++ai) {      \
        printf("%d", ary[ai]);       \
        if(ai < num-1) printf(", "); \
    }                                \
    printf("}\n"); } while(0)

这样它就可以在控制结构之后使用而不用花括号括起来。