名前空間
変種
操作

複合リテラル

提供: cppreference.com
< c‎ | language

指定された型の無名オブジェクトをその場で構築します。 配列型、構造体型、または共用体型の変数が一度だけ必要なときに使用されます。

目次

[編集] 構文

( type ) { initializer-list } (C99以上)

ただし

type - 任意の完全オブジェクト型またはサイズが未知の配列 (VLA は含まれません) を表す型名
initializer-list - type のオブジェクトの初期化に適した初期化子のリスト。

[編集] 説明

複合リテラル式は、 type によって指定された型の無名オブジェクトを構築し、 initializer-list によって指定されたかのようにそれを初期化します。

複合リテラルの型は type です (ただし、 type がサイズの未知な配列の場合は、そのサイズが配列の初期化であるかのように initializer-list から推定されます)。

複合リテラルの値カテゴリは左辺値です (アドレスを取ることができます)。

複合リテラルの評価結果である無名オブジェクトは、その複合リテラルがファイルスコープの場合は静的記憶域期間、その複合リテラルがブロックスコープの場合は自動記憶域期間 (この場合、そのオブジェクトの生存期間は囲っているブロックの終わりで終わります) を持ちます。

[編集] ノート

const 修飾された文字またはワイド文字配列型の複合リテラルは文字列リテラルと記憶域を共有することがあります。

(const char []){"abc"} == "abc" // 1 になることも 0 になることもあります (処理系定義)。

各複合リテラルはそのスコープに単一のオブジェクトのみを作成します。

int f (void)
{
    struct s {int i;} *p = 0, *q;
    int j = 0;
again:
    q = p, p = &((struct s){ j++ });
    if (j < 2) goto again; // 注: もし代わりにループが使用されたならば、
                           // スコープはここで終わり、それによって複合リテラルの生存期間も
                           // 終わり、 p はダングリングポインタになります。
    return p == q && q->i == 1; // 常に 1 を返します。
}

複合リテラルは無名であるため、自分自身を参照することはできません (名前付きの構造体は自分自身へのポインタを持つことができます)。

複合リテラルの構文はキャストと似ていますが、キャストは非左辺値オブジェクト式であるのに対して、複合リテラルは左辺値であるという点が、重要な違いです。

[編集]

int *p = (int[]){2, 4}; // int[2] 型の無名の静的配列を作成し、
                        // その配列を値 {2, 4} に初期化し、
                        // その配列の最初の要素を指すポインタ p を作成します。
const float *pc = (const float []){1e0, 1e1, 1e2}; // 読み込み専用の複合リテラル。
 
int main(void)
{
    int n = 2, *p = &n;
    p = (int [2]){*p}; // int[2] 型の無名の自動配列を作成し、
                       // その第1要素を元々 *p が保持していた値に初期化し、
                       // その第2要素をゼロに初期化し、
                       // その最初の要素のアドレスを p に格納します。
 
    struct point {double x,y;};
    void drawline1(struct point from, struct point to);
    void drawline2(struct point *from, struct point *to);
    drawline1((struct point){.x=1, .y=1},  // ブロックスコープの構造体を2つ作成し、
                                           // それらを値渡しして drawline1 を呼びます。
    drawline2(&(struct point){.x=1, .y=1},  // ブロックスコープの構造体を2つ作成し、
              &(struct point){.x=3, .y=4}); // そのアドレスを渡して drawline2 を呼びます。
}


[編集] 参考文献

  • C11 standard (ISO/IEC 9899:2011):
  • 6.5.2.5 Compound literals (p: 85-87)
  • C99 standard (ISO/IEC 9899:1999):
  • 6.5.2.5 Compound literals (p: 75-77)