Compound literals (since C99)
Constructs an unnamed object of specified type (which may be struct, union, or even array type) in-place.
Contents
[edit] Syntax
(
storage-class-specifiers (optional)(since C23) type )
{
initializer-list }
(since C99)
(
storage-class-specifiers (optional)(since C23) type )
{
initializer-list ,
}
(since C99)
(
storage-class-specifiers (optional) type )
{
}
(since C23)
where
[edit] Explanation
The compound literal expression constructs an unnamed object of the type specified by type and initializes it as specified by initializer-list. Designated initializers are accepted.
The type of the compound literal is type (except when type is an array of unknown size; its size is deduced from the initializer-list as in array initialization).
The value category of a compound literal is lvalue (its address can be taken).
typeof(
type )
ID =
{
initializer-list }
;
[edit] Notes
Compound literals of const-qualified character or wide character array types may share storage with string literals.
(const char []){"abc"} == "abc" // might be 1 or 0, unspecified
Each compound literal creates only a single object in its scope:
#include <assert.h> int main(void) { struct S { int i; } *p = 0, *q; int j = 0; again: q = p, p = &((struct S){ j++ }); // creates an unnamed object of type S, // initializes it to the value formerly // held in j, then assigns the address // of this unnamed object to the pointer p if (j < 2) goto again; // note: if a loop were used, it would end scope here, // which would terminate the lifetime of the compound // literal leaving p as a dangling pointer assert (p == q && q->i == 1); }
Because compound literals are unnamed, a compound literal cannot reference itself (a named struct can include a pointer to itself).
Although the syntax of a compound literal is similar to a cast, the important distinction is that a cast is a non-lvalue expression while a compound literal is an lvalue.
[edit] Example
#include <stdio.h> int *p = (int[]){2, 4}; // creates an unnamed static array of type int[2] // initializes the array to the values {2, 4} // creates pointer p to point at the first element of // the array const float *pc = (const float []){1e0, 1e1, 1e2}; // read-only compound literal struct point {double x,y;}; int main(void) { int n = 2, *p = &n; p = (int [2]){*p}; // creates an unnamed automatic array of type int[2] // initializes the first element to the value formerly // held in *p // initializes the second element to zero // stores the address of the first element in p void drawline1(struct point from, struct point to); void drawline2(struct point *from, struct point *to); drawline1( (struct point){.x=1, .y=1}, // creates two structs with block scope and (struct point){.x=3, .y=4}); // calls drawline1, passing them by value drawline2( &(struct point){.x=1, .y=1}, // creates two structs with block scope and &(struct point){.x=3, .y=4}); // calls drawline2, passing their addresses } void drawline1(struct point from, struct point to) { printf ("drawline1: `from` @ %p {%.2f, %.2f}, `to` @ %p {%.2f, %.2f}\n", (void*)&from, from.x, from.y, (void*)&to, to.x, to.y); } void drawline2(struct point *from, struct point *to) { printf ("drawline2: `from` @ %p {%.2f, %.2f}, `to` @ %p {%.2f, %.2f}\n", (void*)from, from->x, from->y, (void*)to, to->x, to->y); }
Possible output:
drawline1: `from` @ 0x7ffd24facea0 {1.00, 1.00}, `to` @ 0x7ffd24face90 {3.00, 4.00} drawline2: `from` @ 0x7ffd24facec0 {1.00, 1.00}, `to` @ 0x7ffd24faced0 {3.00, 4.00}
[edit] References
- C23 standard (ISO/IEC 9899:2024):
- 6.5.2.5 Compound literals (p: 77-80)
- C17 standard (ISO/IEC 9899:2018):
- 6.5.2.5 Compound literals (p: 61-63)
- 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)