名稱空間
變體
操作

實現定義的行為控制

來自 cppreference.com

實現定義的行為由 #pragma 指令控制。

目錄

[編輯] 語法

#pragma pragma_params (1)
_Pragma ( string-literal ) (2) (C99 起)
1) 以實現定義的方式行為(除非 pragma_params 是下面所示的標準 pragma 之一)。
2)string-literal 中移除編碼字首(如果有)、外部引號以及前導/尾隨空白,將每個 \" 替換為 ",將每個 \\ 替換為 \,然後將結果標記化(如在翻譯階段 3中),然後使用結果,就像輸入到(1)中的#pragma一樣。

[編輯] 解釋

pragma 指令控制編譯器的實現特定行為,例如停用編譯器警告或更改對齊要求。任何未被識別的 pragma 都將被忽略。

[編輯] 標準 pragma

以下三個 pragma 由語言標準定義:

#pragma STDC FENV_ACCESS arg (1) (C99 起)
#pragma STDC FP_CONTRACT arg (2) (C99 起)
#pragma STDC CX_LIMITED_RANGE arg (3) (C99 起)

其中 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 的編譯器可能會提供等效的編譯時選項,例如 gcc 的 -fcx-limited-range-ffp-contract

[編輯] 非標準 pragma

[編輯] #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 控制後續定義的結構體和聯合體成員的最大對齊方式。

#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 可以減少結構體的對齊方式,但不能使結構體過度對齊。

另請參閱 GCCMSVC 的具體細節。

[編輯] 參考

  • 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++ pragma
2.  GCC 支援的 Pragma
3.  IBM AIX XL C 16.1 中的單個 pragma 描述標準 pragma
4.  Sun Studio 11 C++ 使用者指南中的附錄 B. Pragma
5.  Intel C++ 編譯器 pragma
6.  HP aCC 編譯器 pragma