名前空間
変種
操作

処理系定義の動作制御

From cppreference.com
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

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

目次

[編集] 構文

#pragma pragma-params (1)
_Pragma( string-literal ) (2) (C++11以降)
1) 処理系定義の振る舞いをします。
2) string-literal から L プレフィックス (もしあれば)、外側の引用符、先頭/末尾の空白を除去し、各 \"" に、各 \\\ に置き換え、結果をトークン化し (変換フェーズ 3 と同様)、その結果を (1)#pragma への入力として使用します。

[編集] 解説

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

[編集] 非標準プラグマ

ISO C++ 言語標準は、コンパイラがいかなるプラグマもサポートすることを義務付けていません。しかし、いくつかの非標準プラグマが複数の実装でサポートされています。

[編集] #pragma STDC

ISO C 言語標準は、C コンパイラが以下の 3 つのプラグマをサポートすることを義務付けており、一部の C++ コンパイラベンダーは、C++ フロントエンドでそれらをさまざまな程度でサポートしています。

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

ここで argON, OFF, または DEFAULT のいずれかです。

1) ON に設定すると、プログラムが浮動小数点環境にアクセスまたは変更することをコンパイラに通知します。これは、フラグテストやモード変更を妨害する可能性のある最適化 (例: グローバル共通部分式除去、コード移動、定数畳み込み) が禁止されることを意味します。デフォルト値は処理系定義で、通常は OFF です。
2) 浮動小数点式の「縮約 (contracting)」を許可します。これは、式が書かれたとおりに正確に評価された場合に観測されるであろう丸め誤差や浮動小数点例外を省略する最適化です。たとえば、(x * y) + z を単一の融合乗算加算 (fused multiply-add) 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 です。

上記の 3 つのプラグマのいずれかが、すべての外部宣言の外側、または複合ステートメント内のすべての明示的な宣言とステートメントの前に現れる以外のコンテキストで出現した場合、プログラムの動作は未定義です。

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

[編集] #pragma once

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

同じヘッダが複数回インクルードされるのを防ぐ標準的なアプローチは、インクルードガードを使用することです。

#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 once を使用する場合、ファイルはファイルシステムレベルの同一性に基づいて除外されるため、プロジェクト内の複数の場所に存在するヘッダを二重にインクルードすることから保護することはできません。

[編集] #pragma pack

このプラグマ群は、後続で定義されるクラスおよび共用体メンバの最大アラインメントを制御します。

#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 はクラスのアラインメントを減少させる可能性がありますが、クラスをオーバーアラインにすることはできません。

GCC および MSVC の具体的な詳細も参照してください。

[編集] 参照

  • C++23標準 (ISO/IEC 14882:2024)
  • 15.9 Pragma directive [cpp.pragma]
  • C++20 standard (ISO/IEC 14882:2020)
  • 15.9 Pragma directive [cpp.pragma]
  • C++17 standard (ISO/IEC 14882:2017)
  • 19.6 Pragma directive [cpp.pragma]
  • C++14 standard (ISO/IEC 14882:2014)
  • 16.6 Pragma directive [cpp.pragma]
  • C++11 standard (ISO/IEC 14882:2011)
  • 16.6 Pragma directive [cpp.pragma]
  • C++98 標準 (ISO/IEC 14882:1998)
  • 16.6 Pragma directive [cpp.pragma]

[編集] 関連項目

C ドキュメント (Implementation defined behavior control について)

[編集] 外部リンク

1.  Visual Studio の C++ プラグマ
2.  GCC で受け入れられるプラグマ
3.  IBM AIX XL C 16.1 の個々のプラグマの説明標準プラグマ
4.  Sun Studio 11 C++ User's Guide の付録 B. プラグマ
5.  Intel C++ コンパイラのプラグマ
6.  HP aCC A.06.25 のリリースノート (プラグマを含む)
English 日本語 中文(简体) 中文(繁體)