一次性使用后取消定义宏内的常量
Undefining constant inside macro after single use
我想要一个宏,它会在调用时取消定义传递给它的常量。
像这样:
#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;
}
是否可以使用预处理器存档此功能?
我认为使用标准 C 预处理器无法获得它,但可以使用 GCC/CLANG 编译指示,如 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;
使用 gcc
/clang
编译生成:
prog.c:8:11: error: CONSTANT1 expanded more than once
8 | int b = CONSTANT1;
请注意,pragmas push_macro
/pop_macro
非常便携,GCC、CLANG、MSVS 和 Intel C 编译器都支持它们。
失败 CONSTANT1
的更便携版本可能是:
#define CONSTANT1 sizeof(struct {_Static_assert(0, "CONSTANT1 expanded more than once"); int x; })
它需要 C11 兼容的编译器。
我想要一个宏,它会在调用时取消定义传递给它的常量。 像这样:
#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;
}
是否可以使用预处理器存档此功能?
我认为使用标准 C 预处理器无法获得它,但可以使用 GCC/CLANG 编译指示,如 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;
使用 gcc
/clang
编译生成:
prog.c:8:11: error: CONSTANT1 expanded more than once
8 | int b = CONSTANT1;
请注意,pragmas push_macro
/pop_macro
非常便携,GCC、CLANG、MSVS 和 Intel C 编译器都支持它们。
失败 CONSTANT1
的更便携版本可能是:
#define CONSTANT1 sizeof(struct {_Static_assert(0, "CONSTANT1 expanded more than once"); int x; })
它需要 C11 兼容的编译器。