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.