跳到主要内容

由实现定义的行为控制

行为由 ... 控制#pragma指令。

语法

1#pragma
pragma-params
2_Pragma
string-literal
  1. 以由实现定义的方式运行。
  2. 删除 string-literal 的 L 前缀(如果存在)、外部引号以及前导/尾随空格,将每个 \" 替换为 ",将每个 \\ 替换为 \,然后对结果进行标记(如翻译阶段 3),然后将其结果用作 (1)#pragma 的输入。

非标准 pragmas

ISO C++ 语言标准不要求编译器支持任何 pragmas。然而,许多非标准的 pragmas 被多个实现所支持。

#pragma STDC

ISO C 语言标准要求 C 编译器支持以下三个 pragmas,并且一些 C++ 编译器厂商在其 C++ 前端以不同程度支持它们。

1#pragma
STDCFENV_ACCESSarg
2#pragma
STDCFP_CONTRACTarg
3#pragma
STDCCX_LIMITED_RANGEarg

其中 argONOFFDEFAULT

  1. 如果设置为 ON,则告知编译器程序将访问或修改浮点环境,这意味着禁止可能破坏标志测试和模式更改的优化(例如,全局公共子表达式消除、代码移动和常量折叠)。默认值为由实现定义,通常为 OFF
  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,尽管可能存在中间溢出。换句话说,程序员保证传递给这些函数的参数值的范围是有限的。默认值为 OFF

#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

这一系列 pragmas 控制后续定义的类和联合成员的最大对齐方式。

1#pragma
pack ( arg )
2#pragma
pack ( )
3#pragma
pack ( push )
4#pragma
pack ( push, arg)
5#pragma
pack ( pop )

其中 arg 是 2 的幂,表示新的对齐字节数。

  1. 将当前对齐方式设置为值 arg
  2. 将当前对齐方式设置为默认值(通过命令行选项指定)。
  3. 将当前对齐方式的值推送到内部堆栈。
  4. 将当前对齐方式的值推送到内部堆栈,然后将当前对齐方式设置为值 arg
  5. 弹出内部堆栈的顶部条目,然后将当前对齐方式设置为(恢复为)该值。

#pragma pack可以减小类的对齐方式,但是不能使类过对齐。

另请参阅GCCMSVC 的具体详细信息。

重要

本节不完整 原因:解释此 pragmas 对数据成员的影响以及使用它们的优点和缺点。参考来源

重要

本节不完整 原因:无示例

参考文献

  • C++23 标准 (ISO/IEC 14882:2023)
    • 15.9 Pragma 指令 [cpp.pragma]
  • C++20 标准 (ISO/IEC 14882:2020)
    • 15.9 Pragma 指令 [cpp.pragma]
  • C++17 标准 (ISO/IEC 14882:2017)
    • 19.6 Pragma 指令 [cpp.pragma]
  • C++14 标准 (ISO/IEC 14882:2014)
    • 16.6 Pragma 指令 [cpp.pragma]
  • C++11 标准 (ISO/IEC 14882:2011)
    • 16.6 Pragma 指令 [cpp.pragma]
  • C++98 标准 (ISO/IEC 14882:1998)
    • 16.6 Pragma 指令 [cpp.pragma]

由实现定义的行为控制

行为由 ... 控制#pragma指令。

语法

1#pragma
pragma-params
2_Pragma
string-literal
  1. 以由实现定义的方式运行。
  2. 删除 string-literal 的 L 前缀(如果存在)、外部引号以及前导/尾随空格,将每个 \" 替换为 ",将每个 \\ 替换为 \,然后对结果进行标记(如翻译阶段 3),然后将其结果用作 (1)#pragma 的输入。

非标准 pragmas

ISO C++ 语言标准不要求编译器支持任何 pragmas。然而,许多非标准的 pragmas 被多个实现所支持。

#pragma STDC

ISO C 语言标准要求 C 编译器支持以下三个 pragmas,并且一些 C++ 编译器厂商在其 C++ 前端以不同程度支持它们。

1#pragma
STDCFENV_ACCESSarg
2#pragma
STDCFP_CONTRACTarg
3#pragma
STDCCX_LIMITED_RANGEarg

其中 argONOFFDEFAULT

  1. 如果设置为 ON,则告知编译器程序将访问或修改浮点环境,这意味着禁止可能破坏标志测试和模式更改的优化(例如,全局公共子表达式消除、代码移动和常量折叠)。默认值为由实现定义,通常为 OFF
  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,尽管可能存在中间溢出。换句话说,程序员保证传递给这些函数的参数值的范围是有限的。默认值为 OFF

#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

这一系列 pragmas 控制后续定义的类和联合成员的最大对齐方式。

1#pragma
pack ( arg )
2#pragma
pack ( )
3#pragma
pack ( push )
4#pragma
pack ( push, arg)
5#pragma
pack ( pop )

其中 arg 是 2 的幂,表示新的对齐字节数。

  1. 将当前对齐方式设置为值 arg
  2. 将当前对齐方式设置为默认值(通过命令行选项指定)。
  3. 将当前对齐方式的值推送到内部堆栈。
  4. 将当前对齐方式的值推送到内部堆栈,然后将当前对齐方式设置为值 arg
  5. 弹出内部堆栈的顶部条目,然后将当前对齐方式设置为(恢复为)该值。

#pragma pack可以减小类的对齐方式,但是不能使类过对齐。

另请参阅GCCMSVC 的具体详细信息。

重要

本节不完整 原因:解释此 pragmas 对数据成员的影响以及使用它们的优点和缺点。参考来源

重要

本节不完整 原因:无示例

参考文献

  • C++23 标准 (ISO/IEC 14882:2023)
    • 15.9 Pragma 指令 [cpp.pragma]
  • C++20 标准 (ISO/IEC 14882:2020)
    • 15.9 Pragma 指令 [cpp.pragma]
  • C++17 标准 (ISO/IEC 14882:2017)
    • 19.6 Pragma 指令 [cpp.pragma]
  • C++14 标准 (ISO/IEC 14882:2014)
    • 16.6 Pragma 指令 [cpp.pragma]
  • C++11 标准 (ISO/IEC 14882:2011)
    • 16.6 Pragma 指令 [cpp.pragma]
  • C++98 标准 (ISO/IEC 14882:1998)
    • 16.6 Pragma 指令 [cpp.pragma]