Namespaces
Variants

Implementation defined behavior control

From cppreference.net

実装定義の動作は #pragma ディレクティブによって制御されます。

目次

構文

#pragma pragma_params (1)
_Pragma ( string-literal ) (2) (C99以降)
1) 実装定義の動作を示す(ただし pragma_params が以下に示す標準プラグマのいずれかでない場合)。
2) エンコーディング接頭辞(存在する場合)、外側の引用符、および先頭/末尾の空白を string-literal から除去し、各 \" " に、各 \\ \ に置換した後、結果をトークン化し( 翻訳段階3 と同様)、その結果を (1) #pragma への入力として使用する。

説明

プラグマディレクティブは、コンパイラ警告の無効化やアライメント要件の変更など、コンパイラ固有の実装動作を制御します。認識されないプラグマは無視されます。

標準プラグマ

以下の3つのプラグマは言語標準によって定義されています:

#pragma STDC FENV_ACCESS 引数 (1) (C99以降)
#pragma STDC FP_CONTRACT 引数 (2) (C99以降)
#pragma STDC CX_LIMITED_RANGE 引数 (3) (C99以降)

where arg is either ON or OFF or DEFAULT .

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)]/(u 2
+v 2
)
および |x+iy| = x 2
+y 2
を使用する可能性があることをコンパイラに通知します。中間オーバーフローの可能性があるにもかかわらず、プログラマはこれらの関数に渡される値の範囲が限定されていることを保証します。デフォルト値は OFF です。

注記: これらのプラグマをサポートしないコンパイラは、gccの -fcx-limited-range および -ffp-contract のような同等のコンパイル時オプションを提供する場合があります。

非標準プラグマ

#pragma once

#pragma once は非標準のプラグマであり、 大多数の現代コンパイラ でサポートされています。ヘッダーファイル内に記述された場合、同じソースファイル内で(直接または間接的に)複数回インクルードされても、一度だけ解析されることを示します。

同じヘッダーの多重インクルードを防止する標準的なアプローチは、 include guards を使用することです:

#ifndef LIBRARY_FILENAME_H
#define LIBRARY_FILENAME_H
// ヘッダーの内容
#endif /* LIBRARY_FILENAME_H */

これにより、翻訳単位内でのヘッダーの最初のインクルードを除くすべてのインクルードがコンパイルから除外されます。すべてのモダンなコンパイラは、ヘッダーファイルがインクルードガードを使用している事実を記録し、ガードがまだ定義されている限り、ファイルが再度検出されても再解析しません(例: gcc を参照)。

#pragma once を使用すると、同じヘッダーが次のように表示されます

#pragma once
// ヘッダーの内容

ヘッダーガードとは異なり、このプラグマにより複数のファイルで誤って同じマクロ名を使用することが不可能になります。一方、 #pragma once はファイルシステムレベルの同一性に基づいてファイルを除外するため、プロジェクト内で複数の場所に存在するヘッダーを2回インクルードする場合には保護できません。

#pragma pack

このプラグマファミリーは、後続で定義される構造体および共用体メンバーの最大アライメントを制御します。

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

where arg は2の小さなべき乗であり、新しいアラインメントをバイト単位で指定します。

1) 現在のアライメントを値 arg に設定します。
2) 現在のアラインメントをデフォルト値(コマンドラインオプションで指定された値)に設定します。
3) 現在のアライメント値を内部スタックにプッシュします。
4) 内部スタックに現在のアライメント値をプッシュし、その後現在のアライメントを arg の値に設定します。
5) 内部スタックから最上位エントリをポップし、現在のアライメントをその値に設定(復元)します。

#pragma pack は構造体のアライメントを減少させる可能性がありますが、構造体をオーバーアラインさせることはできません。

詳細については、以下の GCC および MSVC のドキュメントも参照してください。

参考文献

  • C23規格 (ISO/IEC 9899:2024):
  • 6.10.6 プラグマ指令 (p: TBD)
  • 6.10.9 プラグマ演算子 (p: TBD)
  • C17規格 (ISO/IEC 9899:2018):
  • 6.10.6 Pragma directive (p: 127)
  • 6.10.9 Pragma operator (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 プラグマ指令(p: 159)
  • 6.10.9 プラグマ演算子(p: 161-162)
  • C89/C90標準 (ISO/IEC 9899:1990):
  • 3.8.6 プラグマ指令

関連項目

C++ documentation for Implementation defined behavior control

外部リンク

1. Visual Studio の C++ プラグマ
2. プラグマ GCC で受け入れられるプラグマ
3. 個別プラグマの説明 および 標準プラグマ IBM AIX XL C 16.1
4. 付録 B. プラグマ Sun Studio 11 C++ ユーザーズガイド
5. Intel C++ コンパイラのプラグマ
6. HP aCC コンパイラのプラグマ