_Pragma和宏替换

前端之家收集整理的这篇文章主要介绍了_Pragma和宏替换前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在实现我自己的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的任何内容.

解决方法

不需要一个禁止_Pragma成为宏名称的特殊规则.有一个领先的下划线和大写字母,它是保留的标识符,你不应该使用,无论如何.使用保留的标识符导致程序的未定义的行为,编译器可能会做任何事情.

一个实现可以将其实现为一个宏,但这应该对你来说是透明的,只要你正确使用它,只要你不会弄乱它.实现必须保证的唯一重要的事情是,在_Pragma的参数的“destringization”和“tokeninzation”就像在阶段3中一样完成(如果它只是“只”一个宏),那么这个结果# pragma指令在第4阶段进行处理.

猜你在找的C&C++相关文章