Namespaces
Variants

Constant expressions

From cppreference.net

いくつかの種類の式は constant expressions として知られています。

目次

プリプロセッサ定数式

#if または #elif に続く式は展開されて

#if 式で評価される文字定数は、ソース文字セット、実行文字セット、またはその他の実装定義の文字セットで解釈される可能性があります。

#if 式における整数演算は、符号付き型については intmax_t のセマンティクスを使用し、符号なし型については uintmax_t のセマンティクスを使用して実行されます。

(C99以降)

整数定数式

整数定数式は、以下のもののみで構成される式です。

  • _Alignof (C23まで) alignas (C23以降) 演算子
(C11以降)
  • 整数型である、または算術型でありキャストの直接のオペランドである名前付きおよび複合リテラル定数
(C23以降)

整数定数式はコンパイル時に評価されます。以下の文脈では、 整数定数式 として知られる式が必要とされます:

(C99以降)
(C11以降)
  • ビット精度整数型( _BitInt ( N ) )のビット数N
(C23以降)

静的初期化子

静的記憶域期間およびスレッドローカル記憶域期間を持つオブジェクトの 初期化子 で使用される式、 または constexpr 記憶クラス指定子で宣言された式は、 (C23以降) 文字列リテラルか、以下のいずれかである可能性のある式でなければなりません

1) 算術定数式 (任意の算術型の式であり、以下で構成される):
(C11以降)
  • 算術型の名前付きまたは複合リテラル定数
(C23以降)
2) 空ポインタ定数(例: NULL )。
3) address constant expression (アドレス定数式)。これは以下を指す:
  • ヌルポインタ
  • lvalue が静的 storage duration を持つオブジェクトまたは関数指示子を指定し、以下のいずれかの方法でポインタに変換されたもの:
  • 単項アドレス取得演算子の使用による
  • 整数定数のポインタへのキャストによる
  • 配列からポインタへの、または関数からポインタへの暗黙の conversion による
4) address constant expression 型の完全オブジェクト型の、プラスまたはマイナスの integer constant expression
5) 名前付き定数。これは以下のいずれかの識別子である:
  • 列挙定数
  • 事前定義定数( true false または nullptr のいずれか)
  • 記憶クラス指定子 constexpr で宣言され、オブジェクト型を持つもの
または、構造体型または共用体型の名前付き定数に対して . メンバアクセス演算子を適用する後置式(再帰的であってもよい)。
6) 複合リテラル定数。これは以下のいずれかである:
  • 記憶クラス指定子 constexpr を持つ 複合リテラル
  • 構造体型または共用体型の複合リテラル定数に対して . メンバアクセス演算子を適用する後置式(再帰的であってもよい)。

構造体定数または共用体定数は、それぞれ構造体型または共用体型を持つ名前付き定数または複合リテラル定数である。メンバアクセス演算子 . が共用体定数のメンバにアクセスする場合、アクセスされるメンバは共用体定数の初期化子によって初期化されるメンバと同じでなければならない。

(C23以降)
7) 実装によって受け入れられる他の形式の定数式。

整数定数式とは異なり、静的初期化子式はコンパイル時に評価される必要はありません。コンパイラはそのような初期化子をプログラム開始前に呼び出される実行可能コードに変換する自由を有します。

static int i = 2 || 1 / 0; // 変数iを値1で初期化

浮動小数点の静的初期化子の値は、実行時に同じ式を実行した値よりも精度が低くなることは決してありませんが、より良い場合があります。

浮動小数点定数式

静的初期化子で使用されない浮動小数点型の算術定数式は、常に実行時と同様に評価され、 現在の丸めモード の影響を受けます ( FENV_ACCESS が有効な場合)。また、 math_errhandling で指定された通りにエラーを報告します。

void f(void)
{
#pragma STDC FENV_ACCESS ON
    static float x = 0.0 / 0.0; // 静的初期化子: 例外を発生させない
    float w[] = { 0.0 / 0.0 };  // 例外を発生させる
    float y = 0.0 / 0.0;        // 例外を発生させる
    double z = 0.0 / 0.0;       // 例外を発生させる
}

注記

式がその型で表現できない値に評価される場合、定数式として使用することはできません。

実装は他の形式の定数式を受け入れる場合があります。しかし、これらの定数式は整数定数式、算術定数式、またはアドレス定数式とは見なされず、したがってこれらの種類の定数式を必要とする文脈では使用できません。例えば、 int arr [ ( int ) + 1.0 ] ; はVLAを宣言します。

参考文献

  • C23規格 (ISO/IEC 9899:2024):
  • 6.6 定数式 (p: 95-96)
  • C17規格 (ISO/IEC 9899:2018):
  • 6.6 定数式 (p: 76-77)
  • C11規格 (ISO/IEC 9899:2011):
  • 6.6 定数式 (p: 106-107)
  • C99規格 (ISO/IEC 9899:1999):
  • 6.6 定数式 (p: 95-96)
  • C89/C90標準 (ISO/IEC 9899:1990):
  • 3.4 定数式

関連項目

C++ documentation for Constant expressions