C Language
複合リテラル
サーチ…
構文
- (型){initializer-list}
備考
Cの標準はC11-§6.5.2.5/ 3で述べている:
カッコで囲まれた型名の後に中カッコで囲まれたイニシャライザのリストが後置された式は複合リテラルです。それは初期化子リストによって値が与えられる無名のオブジェクトを提供します。 99)
そして脚注99によると:
これはキャスト式とは異なります。たとえば、キャストはスカラ型またはvoidのみへの変換を指定し、キャスト式の結果は左辺値ではありません。
ご了承ください:
文字列リテラルとconst修飾型の複合リテラルは、別個のオブジェクトを指定する必要はありません。 101)
101)これにより、実装は、文字列リテラルおよび定数複合リテラルのストレージを、同じまたは重複する表現で共有することができます。
例は標準で与えられます:
C11-§6.5.2.5/ 13:
文字列リテラルと同様に、const修飾された複合リテラルは読み取り専用メモリに置くことができ、共有することもできます。例えば、
(const char []){"abc"} == "abc"
リテラルのストレージが共有されている場合は1が返されます。
複合リテラルの定義/初期化
複合リテラルは、定義されているスコープ内に作成される名前のないオブジェクトです。このコンセプトはC99規格で初めて導入されました。複合リテラルの例
C標準からの例、C11-§6.5.2.5/ 9:
int *p = (int [2]){ 2, 4 };
p
は、2つのintの名前のない配列の最初の要素のアドレスに初期化されます。
複合リテラルは左辺値です。名前のないオブジェクトの保存期間は静的(ファイルスコープでリテラルが表示されている場合)または自動(ブロックスコープでリテラルが表示されている場合)のいずれかで、後者の場合は、制御が囲むブロックを離れるとオブジェクトの有効期間が終了します。
void f(void) { int *p; /*...*/ p = (int [2]){ *p }; /*...*/ }
p
は、2つのintからなる配列の最初の要素のアドレスが割り当てられます。最初の要素は、以前にp
指し示された値を持ち、2番目の要素はゼロです。
ここで、 p
はブロックの最後まで有効です。
指定子付き複合リテラル
(C11からも)
struct point {
unsigned x;
unsigned y;
};
extern void drawline(struct point, struct point);
// used somewhere like this
drawline((struct point){.x=1, .y=1}, (struct point){.x=3, .y=4});
架空の関数drawline
は、 struct point
型の2つの引数を受け取ります。最初の座標値はx == 1
とy == 1
であり、2番目の座標値はx == 3
とy == 4
配列の長さを指定しない複合リテラル
int *p = (int []){ 1, 2, 3};
この場合、配列のサイズは指定されていません。初期化子の長さによって決定されます。
初期化子の長さが指定された配列サイズより小さい複合リテラル
int *p = (int [10]){1, 2, 3};
複合リテラルの残りの要素は暗黙的に0
に初期化され0
。
読み取り専用複合リテラル
複合リテラルは左辺値なので、要素は変更可能です。 読み取り専用の複合リテラルは、 const
修飾子を(const int[]){1,2}
として使用して指定できます。
任意の式を含む複合リテラル
関数の中では、複合リテラルは、C99以降の任意の初期化と同様に、任意の式を持つことができます。
void foo()
{
int *p;
int i = 2; j = 5;
/*...*/
p = (int [2]){ i+j, i*j };
/*...*/
}