Compound literal lifetime and if blocks : <p>This is a theoretical question, I know how to do this unambiguously, but I got curious and dug into the standard and I need a second pair of standards lawyer eyes.</p>

<p>Let's start with two structs and one init function:</p>

<pre><code>struct foo {
    int a;
};
struct bar {
    struct foo *f;
};
struct bar *
init_bar(struct foo *f)
{
    struct bar *b = malloc(sizeof *b);
    if (!b)
        return NULL;
    b-&gt;f = f;
    return b;
}
</code></pre>

<p>We now have a sloppy programmer who doesn't check return values:</p>

<pre><code>void
x(void)
{
    struct bar *b;

    b = init_bar(&amp;((struct foo){ .a = 42 }));
    b-&gt;f-&gt;a++;
    free(b);
}
</code></pre>

<p>From my reading of the standard there's nothing wrong here other than potentially dereferencing a NULL pointer. Modifying <code>struct foo</code> through the pointer in <code>struct bar</code> should be legal because the lifetime of the compound literal sent into <code>init_bar</code> is the block where it's contained, which is the whole function <code>x</code>.</p>

<p>But now we have a more careful programmer:</p>

<pre><code>void
y(void)
{
    struct bar *b;

    if ((b = init_bar(&amp;((struct foo){ .a = 42 }))) == NULL)
        err(1, "couldn't allocate b");
    b-&gt;f-&gt;a++;
    free(b);
}
</code></pre>

<p>Code does the same thing, right? So it should work too. But more careful reading of the C11 standard is leading me to believe that this leads to undefined behavior. (emphasis in quotes mine)</p>

<blockquote>
  <p>6.5.2.5 Compound literals</p>
  
  <p>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, <em>it has automatic storage duration associated with
  the enclosing block</em>.</p>
  
  <p>6.8.4 Selection statements</p>
  
  <p>3 <em>A selection statement is a block</em> whose scope is a strict subset of the scope of its
  enclosing block. Each associated substatement is also a block whose scope is a strict
  subset of the scope of the selection statement.</p>
</blockquote>

<p>Am I reading this right? Does the fact that the <code>if</code> is a block mean that the lifetime of the compound literal is just the if statement?</p>

<p>(In case anyone wonders about where this contrived example came from, in real code <code>init_bar</code> is actually <code>pthread_create</code> and the thread is joined before the function returns, but I didn't want to muddy the waters by involving threads).</p>
