I cannot find any good use, but I did find some notable differences to string literals. The chapter about compound literals only have one occurrence of the word "undefined" and as one can see, it's not applicable to assignments or other modifications in general:
16 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.
So the answer to "is it undefined behavior" seems to be: "No, it's not."
Furthermore, another difference is the lifetime. While string literals always have static storage compound literals do not:
5 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.
That would mean this is completely ok:
char *get_string() {
return "Foobar"; // Ok! Static storage
}
But this is not:
struct my_struct {
int x;
int y;
};
struct my_struct *get_my_struct() {
return &(struct my_struct){0,0}; // Not ok! Automatic storage
}
I also made an experiment. I'm not 100% how to interpret it, because it could both be interpreted as static storage and undefined behavior. This outputted "42":
int main(void) {
struct my_struct *p = get_my_struct();
struct my_struct *t = get_my_struct();
p->x = 42;
printf("%d\n", t->x);
}
However, when I turned on -O2
or -O3
it printed "0" instead, so I'm pretty sure it's undefined behavior. Different results depending on optimization level is a very common symptom of UB. Note though that no warning was issued before I turned on optimization. When I did, I got this:
warning: ‘<Uf3f0>.x’ is used uninitialized in this function [-Wuninitialized]
16 | printf("%d\n", t->x);
| ^~~~~~~~~~~~~~~~~~~~
Another thing worth noting is this:
7 String literals, and compound literals with const-qualified types, need not designate distinct objects
Which would mean that two compound literals without const should designate distinct objects, but this is not true for string literals.
(T0){0}=(T1){0}
can be used to "statically assert" that items of typeT1
can be assigned to items of typeT0
. Sometimes stuff like this is useful in some clever macro magic. The fewer-special-cases-in-the-language point is also good. – Stultz