6.5.2.5 Compound literals

Constraints

1

The type name shall specify an object type or an array of unknown size, but not a variable length array type.

2

No initializer shall attempt to provide a value for an object not contained within the entire unnamed object specified by the compound literal.

3

If the compound literal occurs outside the body of a function, the initializer list shall consist of constant expressions.

Semantics

4

A postfix expression that consists of a parenthesized type name followed by a brace- enclosed list of initializers is a compound literal. It provides an unnamed object whose value is given by the initializer list.[1]

5

If the type name specifies an array of unknown size, the size is determined by the initializer list as specified in 6.7.8, and the type of the compound literal is that of the completed array type. Otherwise (when the type name specifies an object type), the type of the compound literal is that specified by the type name. In either case, the result is an lvalue.

6

The value of the compound literal is that of an unnamed object initialized by the initializer list. If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.

7

All the semantic rules and constraints for initializer lists in 6.7.8 are applicable to compound literals.[2]

8

String literals, and compound literals with const-qualified types, need not designate distinct objects.[3]

9

EXAMPLE 1 The file scope definition

int *p = (int []){2, 4};

initializes p to point to the first element of an array of two ints, the first having the value two and the second, four. The expressions in this compound literal are required to be constant. The unnamed object has static storage duration.

10

EXAMPLE 2 In contrast, in

void f(void)
{
      int *p;
      /*...*/
      p = (int [2]){*p};
      /*...*/
}

p is assigned the address of the first element of an array of two ints, the first having the value previously pointed to by p and the second, zero. The expressions in this compound literal need not be constant. The unnamed object has automatic storage duration.

11

EXAMPLE 3 Initializers with designations can be combined with compound literals. Structure objects created using compound literals can be passed to functions without depending on member order:

drawline((struct point){.x=1, .y=1},
      (struct point){.x=3, .y=4});

Or, if drawline instead expected pointers to struct point:

drawline(&(struct point){.x=1, .y=1},
      &(struct point){.x=3, .y=4});

12

EXAMPLE 4 A read-only compound literal can be specified through constructions like:

(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}

13

EXAMPLE 5 The following three expressions have different meanings:

"/tmp/fileXXXXXX"
(char []){"/tmp/fileXXXXXX"}
(const char []){"/tmp/fileXXXXXX"}

The first always has static storage duration and has type array of char, but need not be modifiable; the last two have automatic storage duration when they occur within the body of a function, and the first of these two is modifiable.

14

EXAMPLE 6 Like string literals, const-qualified compound literals can be placed into read-only memory and can even be shared. For example,

(const char []){"abc"} == "abc"

might yield 1 if the literals’ storage is shared.

15

EXAMPLE 7 Since compound literals are unnamed, a single compound literal cannot specify a circularly linked object. For example, there is no way to write a self-referential compound literal that could be used as the function argument in place of the named object endless_zeros below:

struct int_list { int car; struct int_list *cdr; };
struct int_list endless_zeros = {0, &endless_zeros};
eval(endless_zeros);

16

EXAMPLE 8 Each compound literal creates only a single object in a given scope:

struct s { int i; };
int f (void)
{
      struct s *p = 0, *q;
      int j = 0;
again:
      q = p, p = &((struct s){ j++ });
      if (j < 2) goto again;
          return p == q && q->i == 1;
}

The function f() always returns the value 1.

17

Note that if an iteration statement were used instead of an explicit goto and a labeled statement, the lifetime of the unnamed object would be the body of the loop only, and on entry next time around p would have an indeterminate value, which would result in undefined behavior.

Forward References

Footnotes