プラグマ 1 回


Pragma_once

#pragma Onceです。#の省略はです。
CおよびC++プログラミング言語では、現在のソース ファイルが1 回のコンパイルに 1 回だけインクルードされるように設計された#pragma once、非標準ですが広くサポートされているプリプロセッサ ディレクティブです。したがって、includeguardsと同じ目的を果たしますが、コードの減少、名前の衝突の回避、場合によってはコンパイル速度の向上など、いくつかの利点が一方、必ずしもすべてのコンパイラで利用できるわけではなく、その実装は扱いが難しく、常に信頼できるとは限りません。#pragma once#pragma once

コンテンツ 1 例 2 利点
3 注意事項
4 携帯性
5 参考文献
6 外部リンク


ファイル「祖父母.h」
#プラグマワンスstruct foo { intメンバー; };
ファイル「parent.h」
#include “祖父母.h”
ファイル「child.c」
#include “grandparent.h” #include “parent.h”
この例では、 と の両方に を含めるとgrandparent.h、通常はコンパイル エラーが発生します。これは、指定された名前の構造体は、指定されたコンパイルで 1 回しか定義できないためです。このディレクティブは、後続の の組み込みを無視することでこれを回避します。parent.hchild.c#pragma oncegrandparent.h

利点
#pragma onceを使用すると、C プリプロセッサは、必要な場合にヘッダー ファイルをインクルードし、#includeそれ以外の場合はディレクティブを無視できます。これにはC プリプロセッサ自体の動作を変更する効果があり、プログラマはファイルの依存関係を簡単な方法で表現できるため、手動管理の必要がなくなります。
最も一般的な代替方法は、#include ガードマクロを設定するために#pragma once使用することです。このマクロの名前は、そのファイルに固有になるようにプログラマによって選択されます。例えば、#define
#ifndef GRANDPARENT_H #define GRANDPARENT_H …祖父母の内容。h #endif /* !GRANDPARENT_H */
このアプローチにより、インクルード ファイルの内容が複数回表示されないことが最小限に保証されます。これはより冗長であり、より多くの手動介入が必要であり、複数のファイルで同じマクロ名が誤って使用されることを防止するためのメカニズムがコンパイラに利用できないため、プログラマ エラーが発生しやすくなります。この場合、ファイルは 1 つだけになります。含まれていること。このようなエラーが検出されないままになる可能性はほとんどありませんが、コンパイラ エラー レポートの解釈が複雑になる可能性がプリプロセッサ自体が の処理を​​担当するため#pragma once、プログラマは名前の衝突を引き起こすエラーを犯すことができません。
ディレクティブの周囲に#include ガードがない場合#include、 を使用すると、より#pragma once高レベルのメカニズムであるため、一部のコンパイラのコンパイル速度が向上します。コンパイラ自体は、ヘッダーをスキャンしてとをスキャンするためにC プリプロセッサを呼び出すことなく、ファイル名またはi ノードを比較できます。しかし、インクルード ガードは非常に頻繁に出現し、ファイルを開く際のオーバーヘッドが大きいため、コンパイラがインクルード ガードの処理を最適化し、インクルード ガードを 1 と同じくらい高速にするのが一般的です。 #ifndef#endif#pragma once

注意事項
ファイル システム上で同じファイルを識別することは簡単な作業ではありません。シンボリック リンク、特にハード リンクにより、同じファイルが異なるディレクトリに異なる名前で見つかる可能性がコンパイラは、ファイル サイズ、変更時間、コンテンツを比較するヒューリスティックを使用する場合がさらに、#pragma onceビルドの準備時などに、同じファイルがプロジェクトの複数の部分に意図的にコピーされると、間違った動作をする可能性がインクルード ガードは二重定義から保護しますが、コンパイラ#pragma onceに依存する方法で二重定義を同じファイルとして扱う場合と扱わない場合がこれらの問題は、ハード リンクやネットワーク ファイル システムなどの存在下で同じファイルを構成するものを定義することに関連する問題とともに、これまで の標準化を妨げてきました#pragma once。
#include ガードマクロを使用すると、依存するコードが競合する代替手段のセマンティクスやインターフェイスのわずかな違いを認識して対応できるようになります。例えば、
#include TLS_API_MACRO /* コマンドラインで定義 */…#if 定義された TLS_A_H … 1 つの既知のAPIを使用#elif 定義された TLS_B_H …別の既知のAPIを使用#else #error “認識されない TLS API” #endif
この場合、どの API が利用可能であるかを直接判断するには、インクルード ファイルが#include ガードマクロでそれ自体をアドバタイズしたという事実が利用されます。
ディレクティブ#includeは、ディレクティブの時点で実際にファイルのテキストを含めるというプログラマの意図を表すように定義されます。これは、単一のコンパイル単位内で複数回発生する可能性があり、マクロの定義の変更に対してマクロを含むコンテンツを複数回評価する場合に役立ちます。
インクルード ファイル内での#include ガードマクロの使用と#pragma once同様に、 を使用すると、望ましくない複数のインクルードを防ぐためにその作成者に責任が生じます。プログラマ側がいずれかのメカニズムに過度に依存し、独自の#include ガードを持たずにディレクティブを保護せずに直接使用すると、いずれかのメカニズムで保護されていないインクルード ファイルを使用するときに失敗します。#include

携帯性
コンパイラ
サポート
クラン
はい
コモーC/C++
はい
Cray C および C++
はい (9.0 以降)
C++ビルダー
はい (XE3 以降。クラシック コンパイラのみ。)
デジタル マース C++
はい
GNU コンパイラ コレクション (GCC)
はい (正式には 3.4 以降 )
HP C/aC++
はい (少なくとも A.06.12 以降)
IBM XL C/C++
はい (13.1.1 以降)
インテル C++ コンパイラー
はい
Microsoft Visual C++
はい (4.2 以降)
NVIDIA CUDA コンパイラ はい (基盤となるホスト コンパイラに応じて)
ペレスC
はい
アームDS-5
はい
IAR C/C++
はい
Arm Keil マイクロコントローラー ツール: C/C++ コンパイラー
はい (例: KEIL ARMCC 5)
Oracle 開発者スタジオ C/C++
はい (12.5 以降)
ポートランド グループ C/C++
はい (少なくとも 17.4 以降) TinyCC あり (2015 年 4 月以降)
TASKING VX ツールセット (TriCore 用): C コンパイラー
はい (v6.2r2 以降)
テキサス・インスツルメンツのコード生成ツール: C コンパイラ
はい (例: MSP430、ARM、C2000)

参考文献
^ “一度”。Microsoft ドキュメント。2016 年 11 月 3 日。2019 年7 月 25 日に取得。
^ “内部からのゲーム: インクルードを使用したさらなる実験” . 2005年1月25日。2008 年 9 月 30 日のオリジナルからアーカイブ。2013 年 8 月 19 日に取得。
^ “C プリプロセッサ: 1. C プリプロセッサ” . Gcc.gnu.org。1996 年 2 月 1 日。2013 年 8 月 19 日に取得。
^ “
「Clang」CFE 内部マニュアル — Clang 3.4 ドキュメント」 . Clang.llvm.org 。2013 年 8 月 19 日取得。
^ “clang: ファイル操作ルーチン” . Clang.llvm.org 。2013 年 8 月 19 日に取得。
^ “GCC 3.4 リリース シリーズ — 変更点、新機能、および修正” . Gcc.gnu.org 。2013 年 8 月 19 日に取得。
^ “GCC ソース コードの should_stack_file() 関数” .
^ “clang:clang:Pragma.cpp ソース ファイル” . Clang.llvm.org。2014 年 4 月 4 日にオリジナルからアーカイブされました。2013 年 8 月 19 日に取得。
^ “Comeau C++ プレリリース ユーザー ドキュメント: プラグマ” . Comeaucomputing.com 。2013 年 8 月 19 日に取得。
CS1 メイン: URL-ステータス (リンク)
^ “CCE 9.0.0 リリース概要紹介 S-5212” . 株式会社クレイ 2019-06-01 。。
^ “#pragma Once – RAD Studio XE3” . Docwiki.embarcadero.com。2010-12-02 。2013 年 8 月 19 日に取得。
^ “プラグマス” . デジタルマーズ。2013 年 8 月 19 日に取得。
^ “ラッパー #ifndef の代替” . Gcc.gnu.org 。2013 年 8 月 20 日に取得。
^ “GCC バグ 11569 – #pragma Once に代わるものはありません” . 2003 年 7 月 18 日。。
^ “HP aC++/HP C A.06.29 プログラマーズ ガイド; 2016 年 3 月 (AR1603)” .
^ “GCC プラグマ” . IBM 。2015 年 2 月 20 日に取得。
^ “診断 1782: #pragma Once は廃止されました。代わりに #ifndef ガードを使用して” . インテル開発者ゾーン。2012 年 1 月 31 日のオリジナルからアーカイブ。2013 年12 月 4 日に取得。#pragma Once はインテル コンパイラーで引き続き動作するはずです (現時点では非推奨ではありません)。
^ “1 回 (C/C++)” . Msdn.microsoft.com。2016-08-10 のオリジナルからアーカイブ。2013 年 8 月 19 日に取得。
^ “once プラグマ | Microsoft Docs” .
^ IDE ヘルプ/ドキュメント
^ 「ARM インフォメーション センター」 . アーム。2013 年 12 月 17 日に取得。
^ 「IAR C/C++ 開発ガイド」(PDF)。IAR システム。2023 年3 月 1 日に取得。
^ “コンパイラによって認識されるプラグマ” . ケイル。
^ “Oracle® Developer Studio 12.5: GCC 互換性ガイド” . オラクル。2016 年 7 月 26 日に取得。
^ “ポートランドグループ” . 2016 年7 月 31 日に取得。
^ “TinyCC プラグマ ワンス実装” . 2018 年6 月 19 日に取得。
^ 「MA160-800 (v6.2r2) 2018 年 3 月 13 日 92 ページ」(PDF)。
^ “Texas Instruments – 組み込みソフトウェアとツール #pragma Once の文書 – ソフトウェア問題レポート (SIR)”。

外部リンク
P0538R0 #pragma Once の限定置換