Compound literals in C: do they create duplicate copies?
In the abstract machine (which is how C is defined) the compound literal at block scope creates an object in automatic storage. The object will be destroyed at the end of the function.
"stack" and "heap" are implementation details (which some implementations don't have). The only requirements on the implementation are to produce the same observable behaviour as the abstract machine, it does not have to replicate the abstract machine's memory usage. So the real machine could generate the same executable for both of your examples.
If a compiler can see everything that will be done with a constant literal object, it may be able to omit code that would reserve and release space for it. For example, given:
struct S foo;
...
foo = (struct S foo){1,2,3};
a compiler could generate code that would simply store 1, 2, and 3 directly into the first items of foo
and zero to the rest (if any), rather than generating a new temporary object and copying it.
Unfortunately, there is no way to invite a compiler to refrain from constructing a temporary object in cases where code takes the address of a compound literal and uses it in ways the compiler can't see. Given e.g.
extern void someFunction(struct foo const *p);
...
someOutSideFunction(&(struct foo){1,2,3});
a compiler would not be allowed to substitute:
extern void someFunction(struct foo const *p);
...
static struct foo const __const24601 = {1,2,3};
someOutSideFunction(&__const24601);
unless it knew that someFunction would not both cause the aforementioned function call to get invoked recursively and compare the addresses of the pointers passed to the nested invocations. As of C18, the only way to allow the compiler to generate code that is as efficient as the latter form would be for a programmer to define a named constant object and pass its address as shown in that example.