Home > Software engineering >  Undefining constant inside macro after single use
Undefining constant inside macro after single use

Time:10-20

I would like to have macro which will undefine constant passed to it when called. Something like this:

#define CONSTANT1 123

#define macro(const) \
#ifdef const \
const \
#undef const \
#else \
#error "constant already used once" \
#endif

int main(){
int a = macro(CONSTANT1); // a = 123
int b = macro(CONSTANT1); // <- preprocessor error "constant already used once"
return 0;
}

It is possible to archive this functionality with preprocessor?

CodePudding user response:

I don't think it is possible to get it with standard C preprocessor but it is possible to do it with GCC/CLANG pragmas like push_macro/pop_macro:

// define a macro that will generate error on expansion
#define CONSTANT1 _Pragma("GCC error \"CONSTANT1 expanded more than once\"")

// save this macro and undefine it
#pragma push_macro("CONSTANT1")
#undef CONSTANT1

// let CONSTANT1 expand to 123, but replace with
// previous error-generation macro 
#define CONSTANT1 123 _Pragma("pop_macro(\"CONSTANT1\")") 


int a = CONSTANT1;
int b = CONSTANT1;

Compiling with gcc/clang produced:

prog.c:8:11: error: CONSTANT1 expanded more than once
    8 | int b = CONSTANT1;

Note that pragmas push_macro/pop_macro are quite portable and they are supported by GCC,CLANG,MSVS and Intel C Compiler.

A bit more portable version of failing CONSTANT1 could be:

#define CONSTANT1 sizeof(struct {_Static_assert(0, "CONSTANT1 expanded more than once"); int x; })

It requires C11 compatible compiler.

  • Related