Pragma 指令与 __pragma_Pragma 关键字

Pragma 指令指定计算机特定或操作系统特定的编译器功能。 以 #pragma 开头行指定 pragma 指令。 使用 Microsoft 特定 __pragma 关键字可以在宏定义内编写 pragma 指令。 C99 中引入并由 C++11 采用的标准 _Pragma 预处理器运算符与之类似。

语法

#pragmatoken-string
__pragma(token-string) // 两个前导下划线 - Microsoft 特定扩展
_Pragma(string-literal) // C99

备注

C 和 C++ 的每个实现均支持某些对其主机或操作系统唯一的功能。 例如,某些程序必须对内存中数据的位置进行准确的控制或控制某些函数接收参数的方式。 在保持与 C 和 C++ 语言的总体兼容性的同时,#pragma 指令使每个编译器均能够提供计算机特定和操作系统特定的功能。

根据定义,Pragma 指令是计算机特定或操作系统特定的,并且通常对于每个编译器而言都有所不同。 可以在条件指令中使用 pragma 来提供新的预处理器功能。 或者,使用一个向编译器提供实现定义的信息。

token-string 是一系列字符,这些字符表示特定的编译器指令和参数(如果有)。 数字符号 (#) 必须是包含 pragma 的行上的第一个非空格字符。 空格字符可以分隔数字符号和字“pragma”。 在 #pragma 之后,编写转换器可分析为预处理标记的所有文本。 #pragma 的参数受宏展开的约束。

string-literal 是到 _Pragma 的输入。 删除外引号和前导/尾随空格。 \" 替换为 "\\ 替换为 \

编译器发现它无法识别的 pragma 时,会发出警告,并继续编译。

Microsoft C 和 C++ 编译器识别以下 pragma 指令:

1 仅受 C++ 编译器支持。

Pragma 指令和编译器选项

某些 pragma 指令提供与编译器选项相同的功能。 在源代码中碰到 pragma 时,将重写编译器选项所指定的行为。 例如,如果指定了 /Zp8,则可以使用 pack 为代码的特定部分重写此编译器设置:

cl /Zp8 some_file.cpp
// some_file.cpp - packing is 8
// ...
#pragma pack(push, 1) - packing is now 1
// ...
#pragma pack(pop) - packing is 8 again
// ...

__pragma 关键字

编译器还支持 Microsoft 特定的 __pragma 关键字,该关键字具有与 #pragma 指令相同的功能。 区别在于,__pragma 关键字在宏定义中可内联使用。 #pragma 指令在宏定义中不可用,因为编译器会将指令中的数字符号(“#”)解释为字符串化运算符 (#)

下面的代码示例说明如何在宏中使用 __pragma 关键字。 此代码摘自“编译器 COM 支持示例”中的 ACDUAL 示例中的 mfcdual.h 头:

#define CATCH_ALL_DUAL \
CATCH(COleException, e) \
{ \
_hr = e->m_sc; \
} \
AND_CATCH_ALL(e) \
{ \
__pragma(warning(push)) \
__pragma(warning(disable:6246)) /*disable _ctlState prefast warning*/ \
AFX_MANAGE_STATE(pThis->m_pModuleState); \
__pragma(warning(pop)) \
_hr = DualHandleException(_riidSource, e); \
} \
END_CATCH_ALL \
return _hr; \

_Pragma 预处理运算符

_Pragma 类似于 Microsoft 特定的 __pragma 关键字。 它已引入到 C99 中的 C 标准和 C++ 11 中的 C++ 标准。 仅在指定 /std:c11/std:c17 选项时,它才在 C 中可用。 对于 C++,它在所有 /std 模式下都可用,包括默认模式。

#pragma 不同,_Pragma 可用于将 pragma 指令放入宏定义中。 字符串字面量应为在 #pragma 语句后面另外放置的内容。 例如:

#pragma message("the #pragma way")
_Pragma ("message( \"the _Pragma way\")") 

应转义引号和反斜杠,如上所示。 忽略无法识别的 pragma 字符串。

下面的代码示例说明如何在 assert 类宏中使用 _Pragma 关键字。 它会创建一个 pragma 指令,该指令在条件表达式恰好为常量时禁止显示警告。

宏定义使用多语句宏的 do ... while(0) 习语,以便可以将其当作一个语句来使用。 有关详细信息,请参阅 Stack Overflow 上的 C 多行宏。 示例中的 _Pragma 语句仅适用于其后的代码行。

// Compile with /W4

#include <stdio.h>
#include <stdlib.h>

#define MY_ASSERT(BOOL_EXPRESSION) \
    do { \
        _Pragma("warning(suppress: 4127)") /* C4127 conditional expression is constant */  \
        if (!(BOOL_EXPRESSION)) {   \
            printf("MY_ASSERT FAILED: \"" #BOOL_EXPRESSION "\" on %s(%d)", __FILE__, __LINE__); \
            exit(-1); \
        } \
    } while (0)

int main()
{
    MY_ASSERT(0 && "Note that there is no warning: C4127 conditional expression is constant");

    return 0;
}

另请参阅

C/C++ 预处理器参考
C pragma 指令
关键字