Dre*_*wen 11 c macros undefined-behavior
在实现我自己的C11编译器时,我试图弄清楚如何处理_Pragma关键字/运算符.C11§6.10.9描述_Pragma为运算符,因此似乎可以用宏重新定义它,即#define _Pragma(x) SOME_OTHER_MACRO(x).此外,该声明#undef _Pragma应该没有影响(假设之前没有#define的_Pragma).这类似于关键字#defined的方式,例如旧的VC++ hack #define for if (0) ; else for.但是,因为_Pragma在转换阶段3期间评估运算符,与执行预处理器指令的阶段相同,所以不清楚这是否是异常; 该标准未提及其未定义的行为是否_Pragma用作宏名称.
我使用以下代码对GCC进行了一些测试:
#define PRAGMA _Pragma
PRAGMA("message \"hi\"")
_Pragma ("message \"sup\"")
#undef PRAGMA
#undef _Pragma
//#define _Pragma(x)
_Pragma("message \"hello\"")
Run Code Online (Sandbox Code Playgroud)
使用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\"")
^
Run Code Online (Sandbox Code Playgroud)
如果我添加该行#undef _Alignof,GCC不会抱怨它.
这表明GCC _Pragma通过宏(通过警告消息)实现,并且取消定义它会导致编译错误.如果我取消注释#define _Pragma(x),则错误消失(因为字符串文字消失).
所以,我的问题是:
_Pragma为宏,而不是将其实现为运算符?_Pragma应该是一个运算符,是否定义_Pragma为宏的未定义行为?_Pragma评估和其他预处理程序指令之间是否有任何顺序?或者它们是否具有相同的"优先级"(即它们是按顺序评估的)?同样,通过C11标准,_Pragma除了它是一个可用于#pragma指令的运算符之外,没有提及任何其他内容.
不需要禁止_Pragma成为宏名称的特殊规则.拥有前导下划线和大写字母,无论如何,它都是您不应该使用的保留标识符.使用保留标识符会导致程序的未定义行为,编译器可能会执行任何操作.
一个实现可以将它实现为一个宏,但是只要你正确使用它,这对你来说应该是透明的,只要你不搞乱它.实现必须保证的唯一重要的事情是,对于该参数的"去串化"和"标记化" _Pragma就像在阶段3中一样(如果它"仅"是一个宏则很难)并且结果#pragma指令是在第4阶段处理.
| 归档时间: |
|
| 查看次数: |
2615 次 |
| 最近记录: |