实现定义行为控制

来自cppreference.com

#pragma 指令控制实现定义行为。

目录

[编辑] 语法

#pragma 语用形参 (1)
_Pragma ( 字符串字面量 ) (2) (C99 起)
1) 以实现定义方式行动(除非 语用形参 是后述的标准 pragma 之一)。
2) 移除 字符串字面量 的编码前缀(若存在)、外层引号,及开头/尾随空白符,将每个 \"" ,每个 \\\ 替换,然后记号化结果(如翻译阶段 3 中),再如同在 (1) 中输出到 #pragma 一般使用结果。

[编辑] 解释

pragma 指令控制编译器的实现指定行为,如禁用编译器警告或更改对齐要求。忽略任何不被识别的 pragma 。

[编辑] 标准 pragma

语言标准定义下列三个 pragma :

#pragma STDC FENV_ACCESS 实参 (1)
#pragma STDC FP_CONTRACT 实参 (2)
#pragma STDC CX_LIMITED_RANGE 实参 (3)

其中 实参ONOFFDEFAULT 之一。

1) 若设为 ON ,则告知编译器程序将访问或修改浮点环境,这意味着禁用可能推翻标志测试和模式更改(例如,全局共用子表达式删除、代码移动,及常量折叠)的优化。默认值为实现定义,通常是 OFF
2) 允许缩略浮点表达式,即忽略舍入错误和浮点异常的优化,被观察成表达式以如同书写方式准确求值。例如,允许 (x*y) + z 的实现使用单条融合乘加CPU指令。默认值为实现定义,通常是 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 的编译器可能提供等价的编译时选项,例如 gcc 的 -fcx-limited-range-ffp-contract

[编辑] 非标准 pragma

[编辑] #pragma once

#pragma once 是受到大量主流现代编译器支持的非标准语用。若它出现于头文件,则它指示编译器只分析头文件一次,即使在同一源文件中(直接或间接)包含了多次该头文件。

阻止同一头文件的多次包含的标准方式是使用包含防护

#ifndef LIBRARY_FILENAME_H
#define LIBRARY_FILENAME_H
// 头文件的内容
#endif /* LIBRARY_FILENAME_H */

从而首次以外的头文件包含都被排除出编译。所有现代编译器都记录头文件使用包含防护的事实,而若再遇到该头文件就不再分析它,只要防护仍有定义(例子见 gcc )。

使用 #pragma once ,头文件能出现为

#pragma once
// 头文件的内容

不同于头文件防护,此语用使得编译器不可能错误地在多于一个文件中使用相同的宏名。另一方面,因为基于其文件系统层次的身份排除带 #pragma once 的文件,故若头文件在项目中有多于一个位置,则这不能防止包含它两次。

[编辑] #pragma pack

[编辑] 引用

  • C11 standard (ISO/IEC 9899:2011):
  • 6.10.9 Pragma operator (p: 178)
  • C99 standard (ISO/IEC 9899:1999):
  • 6.10.6 Pragma directive (p: 159)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 3.8.6 Pragma directive

[编辑] 参阅

实现定义行为控制C++ 文档

[编辑] 外部链接