- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在实现我自己的 C11 编译器时,我试图弄清楚如何准确处理 _Pragma
关键字/运算符。 C11 §6.10.9 将 _Pragma
描述为运算符,因此似乎可以使用宏重新定义它,即 #define _Pragma(x) SOME_OTHER_MACRO(x)
。此外,语句 #undef _Pragma
应该没有效果(假设 _Pragma
之前没有 #define
)。这类似于关键字可以被 #define
d 的方式,例如旧的 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
定义为宏,而不是将其作为运算符实现?_Pragma
应该是一个运算符,那么将 _Pragma
定义为宏是否是未定义的行为?_Pragma
评估和其他预处理器指令之间是否有任何顺序?或者它们是否具有相同的“优先级”(即它们按顺序评估)?同样,查看 C11 标准没有提及任何关于 _Pragma
的内容,除了它是一个可用于 #pragma
指令的运算符。
最佳答案
不需要特殊规则来禁止 _Pragma
成为宏名称。有一个前导下划线和大写字母,无论如何,它是您不应该使用的保留标识符之一。使用保留标识符会导致程序出现未定义的行为,编译器可能会做任何事情。
一个实现可以将它实现为一个宏,但这对您来说应该是透明的,只要您正确使用它,只要您不乱用它。实现必须保证的唯一重要的事情是 _Pragma
的参数的“去字符串化”和“tokeninzation”就像在阶段 3 中一样完成(如果它“只是”宏),并且生成的 #pragma
指令在阶段 4 中处理。
关于c - _Pragma 和宏替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24915787/
我正在尝试在 #define 中使用 #pragma。我正在做这样的事情: // I assume this is a correct syntax. Please point out if it i
在实现我自己的 C11 编译器时,我试图弄清楚如何准确处理 _Pragma 关键字/运算符。 C11 §6.10.9 将 _Pragma 描述为运算符,因此似乎可以使用宏重新定义它,即 #define
_Pragma 的参数是一个字符串,所以我认为当您以正常的 c 预处理器方式将字符串粘贴在一起(即,将它们彼此相邻)时,您可以为 _Pragma 的参数形成一个新字符串。然而 _Pragma("GCC
我想要一个像这样调用的宏: GCC_WARNING(-Wuninitialized) 扩展成这样的代码: _Pragma("GCC diagnostic ignored \"-Wuninitializ
我试图在从宏扩展的代码中禁用 g++ 警告。据我了解,_Pragma 应遵循宏用法,并且在使用 g++ 编译时不应触发 Wparentheses: #include #define TEST(exp
我想通过创建适当的宏来简化一些预处理器代码。我想包装 #ifdef _OPENMP _Pragma("omp critical(stdout)") #endif 成单 _OMP_CRITICA
我正在尝试做类似于 another question 的事情,即有条件地在我的程序中包含 OpenMP 编译指示。但是,我想更进一步,避免用户每次使用 pragma 时都需要指定 omp。换句话说,我
是否有类似 ANSI C 运算符 _Pragma 的东西?在 Visual C++ 中? 例如,我试图定义以下宏: #ifdef _OPENMP #define PRAGMA_IF_OPENMP(x)
如果使用 gcc -E 进行预处理,以下代码会从 _Pragma("GCC error") 中产生一些错误: _Pragma("GCC error \"ERROR\"") // error #defi
看了一些Objective-c的代码,发现界面上面有这句话,谁能告诉我是什么意思,或者感谢提供一些关于clang的教程,非常感谢 最佳答案 在较新版本的 Objective-C 编译器 (clang)
我是一名优秀的程序员,十分优秀!