Simulating scope in C macros

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.

Solutions

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

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

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)

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.

Tags: C / Macros / Scope

Similar questions

Preventing Python webbrowser.open() from dominating screen and preventing other processes. Is it possible to open as minimised?
I am using webbroswer.open() in a loop to download multiple files at given intervals. The issue I am having is that whenever the browser window opens, it becomes the primary window and thereby interrupts and disrupts my ability to use the computer. Downloading multiple files means this can last some time. The broswer continuously flashing open is o...
How to replace every function call with the wrapper call in the original class?
I have two classes, one of which is a wrapper of the other. A function in the original class uses a method called forward, but I want it to use the forward method of the wrapper class after it has been wrapped, not the original. For example: Because the wrapper class has the long and convoluted code that needs to be run, I want all calls of forward...
How to begin writing a python wrapper around another wrapper?
I know this question has been asked by one or two people but it's somehow different from what I have in mind. Please bear with me. I'm trying to write a wrapper around the existing couchdb-python wrapper. The reason for this is that in the event that we decide to switch to another NoSQL database in the future, for example MongoDB, I only have to ch...
Wrapper Classes : Creating a python wrapper for a C project
I am new to programming in python,but have programmed in C. I am working on a project called EtherDogs which is a network packet analyzer. How do I go about writing a python wrapper for the project ? It would not be difficult if I had to do a C++ wrapper for it but how do I do it in python ?
When creating a wrapper class in python, how do I get the superclass's methods to return an instance of my wrapper class
For example if I create a simple wrapper around a pandas dataframe: and then I instantiate it.. it works. But, if I call a a dataframe method on it that returns a dataframe, It is no loger an instance of my wrapper class. How do I get it to return an instance of MyDataFrame for all DataFrame methods? Is this a common issue? Am I approaching this in...
python: import com.oceanoptics.omnidriver.api.wrapper.Wrapper
I am trying to import the following api wrapper / device driver as in this python package: Python just returns that there is no module named like this: I installed Omnidriver from the device manufacturer's website. Specifically, I used the installer OmniDriver-2.37-win32-installer.exe and installed the "Development version". It installs a bunch of ...

Also ask

We use cookies to deliver the best possible experience on our website. By continuing to use this site, accepting or closing this box, you consent to our use of cookies. To learn more, visit our privacy policy.