Any workaround for self-referencing macros in C? I want to add a macro

I have a file that uses a macro FLAGS

from include that I have no control over. What is in FLAGS

is incompatible. Sometimes I need to change FLAGS

to add a flag to it. Now I know I can't do it #define FLAGS FLAGS|MY_FLAG

, but I thought that if I was storing FLAGS

in a temporary variable, then I could define and redefine it using the temporary and my flag. For example:

// Assume this next line is what in the include file
#define FLAGS   (1|2|4)

// The rest of this is source, assume compile with -DMOD
#ifdef MOD
#define TEMP (FLAGS|8)
#undef FLAGS
#define FLAGS TEMP
#endif

int main()
{
printf("0x%x\n", FLAGS);
}

      

And if the MOD

error is defined equals error: 'FLAGS' was not declared in this scope

. I know that I can change all the actual C code it uses FLAGS

instead of using it FLAGS|MY_FLAG

, but I was hoping to change the macro and not all the code.

+3


source to share


2 answers


You can do something logically equivalent #define FLAGS FLAGS|MY_FLAG

if you define the macro to be mutable using Boost's "evaluated slots" :

#include <boost/preprocessor/slot/slot.hpp>

// define FLAGS as a modifiable macro and create a setter for it
#define FLAGS BOOST_PP_SLOT(1)
#define UPDATE_FLAGS BOOST_PP_ASSIGN_SLOT(1)

int main(void) {
    // set the initial value of FLAGS
    #define BOOST_PP_VALUE (1|2|4)
    #include UPDATE_FLAGS

    printf("0x%x\n", FLAGS);  // 0x7

    // update FLAGS with a new value using the old one
    #define BOOST_PP_VALUE (FLAGS|8)
    #include UPDATE_FLAGS

    printf("0x%x\n", FLAGS);  // 0xf
}

      



Even though it is sorcery, it is completely standard C, no extensions. Only works for integers.

(It works by taking advantage of something important: macros are not just expanded into code, but must also be expanded to determine whether to follow a branch #if

. Since directives are #if

also capable of evaluating integer math, this can expand the actual numeric value and use its to build a new extension for PP_SLOT

that doesn't include a reference to any macro name. It's all hidden behind directives #include UPDATE_FLAGS

.)

+1


source


Your only real way to do what you are trying to do is by defining an additional macro

// Assume this next line is what in the include file
#define FLAGS_FOR_A (1|2|4)
#define FLAGS   FLAGS_FOR_A

// The rest of this is source, assume compile with -DMOD
#ifdef MOD
#undef FLAGS
#define FLAGS ( FLAGS_FOR_A | 8 )
#endif

int main()
{
    printf("0x%x\n", FLAGS);
}

      



Macros simply perform substitution of plain text computed before execution

+3


source







All Articles