Constructs an unnamed object of specified type (which may be struct, union, or even array type) in-place.
Contents |
(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
| storage-class-specifiers | - | (since C23) A list ofstorage class specifiers that can contain onlyconstexpr,static,register, orthread_local |
| type | - | atype name specifying any complete object type or an array of unknown size, but not a VLA |
| initializer-list | - | list of initializers suitable forinitialization of an object oftype |
The compound literal expression constructs an unnamed object of the type specified bytype and initializes it as specified byinitializer-list.Designated initializers are accepted.
The type of the compound literal istype (except whentype is an array of unknown size; its size is deduced from theinitializer-list as inarray initialization).
The value category of a compound literal islvalue (its address can be taken).
| The unnamed object to which the compound literal evaluates has staticstorage duration if the compound literal occurs at file scope and automaticstorage duration if the compound literal occurs at block scope (in which case the object'slifetime ends at the end of the enclosing block). | (until C23) | |||||||||||||||||||||||
If the compound literal is evaluated outside the body of a function and outside of any parameter list, it is associated with file scope; otherwise, it is associated with the enclosing block. Depending on this association, the storage-class specifiers (possibly empty), type name, and initializer list, if any, shall be such that they are valid specifiers for an object definition in file scope or block scope, respectively, of the following form:
| (since C23) | |||||||||||||||||||||||
Compound literals of const-qualified character or wide character array types may share storage withstring literals.
(constchar[]){"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 pif(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 pointerassert(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 acast, the important distinction is that a cast is a non-lvalue expression while a compound literal is an lvalue.
#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 arrayconstfloat*pc=(constfloat[]){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}