由实现定义的行为控制
来自cppreference.com
< cpp | preprocessor
由实现定义的行为通过 #pragma
指令予以控制。
目录 |
[编辑] 语法
#pragma pragma_params
|
(1) | ||||||||
_Pragma ( 字符串字面量 )
|
(2) | (C++11 起) | |||||||
1) 的行为由实现定义。
2) 移除字符串字面量的
L
前缀(如果有),两边的引号,以及开头/末尾的空白,将每个 \"
替换为 "
,每个 \\
替换为 \
,然后将结果进行记号分解(如翻译阶段 3 的行为),再将其结果作为如同 (1) 中对 #pragma
的输入。[编辑] 解释
语用(Pragma)指令控制编译器的由实现定义的行为,比如禁用编译器警告或者改变对齐要求等。任何未能识别的语用都被忽略。
[编辑] 非标准的语用
ISO C++ 语言标准并不要求编译器支持任何语用。不过,多种实现都支持几种非标准的语用:
[编辑] #pragma STDC
ISO C 语言标准要求 C 编译器支持下列三种语用,一些 C++ 编译器供应商在它们的 C++ 前端中以不同的程度支持它们:
#pragma STDC FENV_ACCESS arg
|
(1) | ||||||||
#pragma STDC FP_CONTRACT arg
|
(2) | ||||||||
#pragma STDC CX_LIMITED_RANGE arg
|
(3) | ||||||||
其中 arg 可以为 ON
或 OFF
或 DEFAULT
。
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
,而不管其中间可能发生的溢出。换句话说,程序员保证传递给这些函数的值的范围是有所限制的。其默认值为
+v2
) 和 |x+iy| = √x2
+y2
,而不管其中间可能发生的溢出。换句话说,程序员保证传递给这些函数的值的范围是有所限制的。其默认值为
OFF
。如果以上任何三条语用并非出现于所有外部声明外面的语境中,或者在组合语句中并非处于所有明确的声明和语句之前,则程序的行为是未定义的。
[编辑] #pragma once
#pragma once是一个受到大量主流现代编译器支持的非标准语用(pragma)。若它出现在头文件中,则它指示头文件只被分析一次,即使头文件在同一源文件中被(直接或间接)包含多次也是如此。
避免多次包含同一头文件的标准手法是使用包含防护:
#ifndef FILENAME_H #define FILENAME_H // 头文件的内容 #endif /* FILENAME_H */
从而在任意翻译单元中,该头文件的除了其首次以外的包含都会在编译中排除。
用 #pragma once,同样的头文件写为
#pragma once // 头文件的内容
不同于头文件防护,这一语用令错误地在多个文件中使用同一宏名变得不可能。另一方面,因为带有 #pragma once 的头文件是基于文件系统级的识别来进行排除的,故若一个头文件在项目中存在多个位置,则无法保障它不被包含两次。
[编辑] #pragma pack
本节未完成 |
[编辑] 另请参阅
由实现定义的行为控制的 C 文档
|
[编辑] 外部连接
- C++ pragmas in Visual Studio 2015
- Pragmas accepted by GCC 4.9.2
- Individual pragma descriptions and Standard pragmas in IBM AIX XL C 13.1
- Appendix B. Pragmas in Sun Studio 11 C++ User's Guide
- Intel C++ compiler pragmas
- HP aCC compiler pragmas