Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

  1. トップページ
  2. C言語辞典
  3. #pragma / #error / #warning

#pragma / #error / #warning

プリプロセッサの補助的な命令です。『#pragma』はコンパイラ固有の動作を制御し、『#error』はコンパイルを強制中断してメッセージを表示します。『#warning』は警告メッセージを出力します。

構文
// コンパイラ固有の制御を行います(コンパイラによって動作が異なります)。
#pragma 命令

// 二重インクルード防止の簡潔な記法です(多くのコンパイラがサポート)。
#pragma once

// コンパイルを強制停止してエラーメッセージを表示します。
#error エラーメッセージ

// 警告メッセージを表示します(GCC / Clang などでサポート)。
#warning 警告メッセージ

// 構造体のパディングを制御します(移植性に注意)。
#pragma pack(n)   // n バイト境界でアライメントします。
#pragma pack()    // デフォルト設定に戻します。
主な命令一覧
命令概要
#pragma onceそのヘッダファイルを1度だけインクルードすることをコンパイラに指示します。多くのコンパイラで対応していますが、C標準ではありません。
#pragma pack(n)構造体のメンバアライメントをnバイト境界に設定します。ネットワークプロトコルや外部バイナリ形式と構造体を合わせる際に使います。
#pragma warning特定の警告を有効化・無効化します(Visual C++ などでサポート)。
#errorプリプロセッサ段階でコンパイルを中断し、指定したメッセージをエラーとして表示します。
#warningプリプロセッサ段階で警告メッセージを表示します。コンパイルは継続されます。GCC・Clangでサポートされています。
サンプルコード
// myheader.h の例
// #pragma once でヘッダガードを簡潔に書きます。
#pragma once

#define MY_HEADER_DEFINED

// C言語の規格を確認してコンパイルを制御します。
#if __STDC_VERSION__ < 199901L
    #error "このコードはC99以降が必要です。"
#endif

// 将来廃止予定の機能に警告を出します(GCC / Clang)。
// #warning "この関数は非推奨です。new_func() を使ってください。"
// main.c の例
#include <stdio.h>

// 構造体のパディングなしでメモリ配置します(ネットワークパケットの例)。
#pragma pack(1)
typedef struct {
    unsigned char  type;    // 1バイト
    unsigned short length;  // 2バイト(パディングなし)
    unsigned int   data;    // 4バイト
} PacketHeader;
#pragma pack() // デフォルトに戻します。

// パディングありの場合と比較します。
typedef struct {
    unsigned char  type;
    unsigned short length;
    unsigned int   data;
} PacketHeaderPadded;

int main(void) {
    printf("pack(1) 適用時のサイズ: %zu バイト\n", sizeof(PacketHeader));
    // 『7』と出力されます(パディングなし)。

    printf("通常のサイズ: %zu バイト\n", sizeof(PacketHeaderPadded));
    // 環境によりますが、アライメントにより8以上になることがあります。

    return 0;
}
概要

『#pragma』は規格上「コンパイラが認識しない場合は無視する」と定められています。そのためコンパイラごとにサポートされる命令が異なります。『#pragma pack』は構造体のメモリ配置を変更するため、誤用するとアライメント違反を引き起こしてパフォーマンス低下やクラッシュを招くことがあります。ネットワークパケットなど特定の目的に限って使用してください。

『#error』は必須の前提条件(C規格バージョン・特定のマクロ定義・ターゲットアーキテクチャなど)を強制チェックするのに役立ちます。条件付きコンパイルと組み合わせることで、誤った環境でのビルドを早期に検出できます。

条件付きコンパイルの詳細は『#ifdef / #ifndef / #endif』を、マクロ定義については『#include / #define(定数)』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。