3

I have the following macro to print out the contents of an array of integers for debug purposes:

#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");

The problem I am having is that when I use it more than once, some compilers complain that I am redefining ai.

Is there a way to make the identifier different for each invocation of the macro? I can come up with a naming scheme that would have a very low change of name collisions, but I'd like to make it automatic.

I know I could use a function, but I am still curious, since I would like to know if there is a way to do this with macros.

tlehman
  • 5,125
  • 2
  • 33
  • 51

3 Answers3

6

Why don't you use a classic do-while trick? For example:

#define FOO(EXPR) \
  do { \
    (EXPR); \
  } while(0)
  • 1
    For more information on why `do {...} while(0)` should always be used with multi statement macros, see http://stackoverflow.com/a/1067238/146041 – Aaron McDaid Dec 07 '13 at 22:59
2

You can just put it into it's own scope, e.g. surround it with { and }

Like this:

#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");                   \
}

I also added parantheses around the num parameter, so you can use a complex expression without having strange sideffects.

WRT to your identifier naming:

You can use macro expansion to change the name using a parameter, but as there are not counter or loop constructs in all c preprocessors I know, I don't think it's possible to automatically change the identifier after every user. Another way would be to have the macro redefine itself every time, but afaik that's also not possible.

Edit:

As has been pointed out (thanks to Aaron McDaid, also see the link he posteed: https://stackoverflow.com/a/1067238/146041), you should use a do { } while(0) construct around your code, so your macro would become:

#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)
Community
  • 1
  • 1
griffin
  • 1,261
  • 8
  • 24
2

If your C is C99-compliant, put ai's declaration in the for loop's header. You should also surround the code with 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)

so that it could be used after control structures without surrounding it with curly braces.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523