在实现我自己的C11编译器时,我试图找出如何处理_Pragma关键字/运算符. C11§6.10.9将_Pragma描述为一个运算符,所以似乎有可能用宏重新定义它,即#define _Pragma(x)SOME_OTHER_MACRO(x).此外,#undef _Pragma的声明应该没有任何效果(假设没有_Pragma的先前的#define).这类似于关键字如何#defined,如旧的VC hack #define for if(0);其他的.但是,由于_Pragma运算符在转换阶段3期间被执行,与执行预处理器指令相同,所以不清楚这是否是异常;该标准没有提到它的未定义行为是否使用_Pragma作为宏名称.
我用GCC做了一些测试,使用下面的代码:
#define PRAGMA _Pragma PRAGMA("message \"hi\"") _Pragma ("message \"sup\"") #undef PRAGMA #undef _Pragma //#define _Pragma(x) _Pragma("message \"hello\"")
编译gcc -std = c11 -pedantic -Wall -Wextra -c输出:
tmp.c:2:1: note: #pragma message: hi PRAGMA("message \"hi\"") ^ tmp.c:4:1: note: #pragma message: sup _Pragma ("message \"sup\"") ^ tmp.c:8:8: warning: undefining "_Pragma" [enabled by default] #undef _Pragma ^ tmp.c:10:9: error: expected declaration specifiers or ‘...’ before string constant _Pragma("message \"hello\"") ^
如果我添加#undef _Alignof行,GCC不会抱怨.
这表明GCC通过宏(通过警告消息)来实现_Pragma,并且不定义它会导致编译错误.如果我取消注释#define _Pragma(x),则该错误消失(因为字符串文字消失).
所以我的问题是:
>实现允许将_Pragma定义为一个宏,而不是将其作为运算符实现?
>如果不是,GCC错了吗?
>如果_Pragma应该是一个运算符,是否定义_Pragma作为宏的未定义的行为?
> _Pragma评估和其他预处理指令之间是否有任何排序?或者他们是否具有相同的“优先级”(即按顺序评估)?
再次,通过C11标准,除了可以用于#pragma指令的操作符之外,并没有提到关于_Pragma的任何内容.