实现定义行为控制
来自 cppreference.cn
实现定义行为由 #pragma
指令控制。
目录 |
[编辑] 语法
#pragma pragma_params |
(1) | ||||||||
_Pragma ( string-literal ) |
(2) | (自 C99 起) | |||||||
1) 以实现定义的方式运行(除非 pragma_params 是下面显示的标准 pragmas 之一)。
2) 从 string-literal 中删除编码前缀(如果有)、外引号和前导/尾随空格,将每个
\"
替换为 "
,将每个 \\
替换为 \
,然后对结果进行标记化(如 翻译阶段 3 中所示),然后将结果用作 (1) 中 #pragma
的输入。[编辑] 解释
pragma 指令控制编译器的实现特定行为,例如禁用编译器警告或更改对齐要求。任何无法识别的 pragma 都会被忽略。
[编辑] 标准 pragmas
以下三个 pragmas 由语言标准定义
#pragma STDC FENV_ACCESS arg |
(1) | (自 C99 起) | |||||||
#pragma STDC FP_CONTRACT arg |
(2) | (自 C99 起) | |||||||
#pragma STDC CX_LIMITED_RANGE arg |
(3) | (自 C99 起) | |||||||
其中 arg 是 ON
或 OFF
或 DEFAULT
。
2) 允许浮点表达式的收缩,即省略舍入误差和浮点异常的优化,如果在表达式完全按照书写方式求值时会观察到这些误差和异常。例如,允许使用单个融合乘加 CPU 指令实现 (x * y) + z。默认值是实现定义的,通常为
ON
。3) 通知编译器复数的乘法、除法和绝对值可以使用简化的数学公式 (x+iy)×(u+iv) = (xu-yv)+i(yu+xv),(x+iy)/(u+iv) = [(xu+yv)+i(yu-xv)]/(u2
+v2
),和 |x+iy| = √x2
+y2
,尽管可能发生中间溢出。换句话说,程序员保证传递给这些函数的值的范围是有限的。默认值为
+v2
),和 |x+iy| = √x2
+y2
,尽管可能发生中间溢出。换句话说,程序员保证传递给这些函数的值的范围是有限的。默认值为
OFF
注意:不支持这些 pragmas 的编译器可能会提供等效的编译时选项,例如 gcc 的 -fcx-limited-range
和 -ffp-contract
。
[编辑] 非标准 pragmas
[编辑] #pragma once
#pragma once 是一个非标准 pragma,受到绝大多数现代编译器的支持。如果它出现在头文件中,则表示即使在同一源文件中多次(直接或间接)包含它,也只应解析一次。
防止多次包含同一头文件的标准方法是使用包含保护
#ifndef LIBRARY_FILENAME_H #define LIBRARY_FILENAME_H // contents of the header #endif /* LIBRARY_FILENAME_H */
以便在任何翻译单元中,除第一次包含头文件外,所有后续包含都被排除在编译之外。所有现代编译器都会记录头文件使用包含保护的事实,并且如果再次遇到该文件,则不会重新解析该文件,只要保护仍然定义(例如,请参阅 gcc)。
使用 #pragma once,相同的头文件显示为
#pragma once // contents of the header
与头文件保护不同,此 pragma 使不可能在一个以上的文件中错误地使用相同的宏名称。另一方面,由于使用 #pragma once 文件是根据其文件系统级别的标识排除的,因此如果头文件在一个项目中存在于多个位置,则无法防止头文件被包含两次。
[编辑] #pragma pack
此 pragma 系列控制后续定义的结构和联合成员的最大对齐方式。
#pragma pack(arg)
|
(1) | ||||||||
#pragma pack()
|
(2) | ||||||||
#pragma pack(push)
|
(3) | ||||||||
#pragma pack(push, arg)
|
(4) | ||||||||
#pragma pack(pop)
|
(5) | ||||||||
其中 arg 是 2 的小幂,并以字节为单位指定新的对齐方式。
1) 将当前对齐方式设置为值 arg。
2) 将当前对齐方式设置为默认值(由命令行选项指定)。
3) 将当前对齐方式的值压入内部堆栈。
4) 将当前对齐方式的值压入内部堆栈,然后将当前对齐方式设置为值 arg。
5) 从内部堆栈中弹出顶部条目,然后将当前对齐方式设置为(恢复)该值。
#pragma pack 可能会减小结构的对齐方式,但是,它不能使结构过度对齐。
本节不完整 原因:解释这些 pragmas 对数据成员的影响,以及使用它们的优缺点。参考来源 |
本节不完整 原因:没有示例 |
[编辑] 参考
- C17 标准 (ISO/IEC 9899:2018)
- 6.10.6 Pragma 指令 (p: 127)
- 6.10.9 Pragma 运算符 (p: 129)
- C11 标准 (ISO/IEC 9899:2011)
- 6.10.6 Pragma 指令 (p: 174)
- 6.10.9 Pragma 运算符 (p: 178)
- C99 标准 (ISO/IEC 9899:1999)
- 6.10.6 Pragma 指令 (p: 159)
- 6.10.9 Pragma 运算符 (p: 161-162)
- C89/C90 标准 (ISO/IEC 9899:1990)
- 3.8.6 Pragma 指令
[编辑] 参见
C++ 文档 关于 实现定义行为控制
|
[编辑] 外部链接
1. | Visual Studio 2019 中的 C++ pragmas |
2. | Pragmas 被 GCC 接受 |
3. | 单个 pragma 描述 和 标准 pragmas 在 IBM AIX XL C 16.1 中 |
4. | 附录 B. Pragmas 在 Sun Studio 11 C++ 用户指南中 |
5. | Intel C++ 编译器 pragmas |
6. | HP aCC 编译器 pragmas |