Search code examples
clanguage-lawyerc99initializertemporary-objects

Taking address of temporary (compound literal) parameter in C


I can't imagine this isn't already duplicate, but I can't easily find the answer since the more complex scenarios specifically to C++ seem to dominate the discussion0.

Is it legal to take take the address of a temporary constructed in the parameter list of a function call in C99?

For example, something like init_list or init_desig_init as follows:

typedef struct {
  int x;
  int y;
} point_t;

int manhattan(point_t *p) {
  return p->x + p->y;
}

int init_list() {
  return manhattan(&(point_t){1, 2});
}

int init_desig_init() {
  return manhattan(&(point_t){.x = 1});
}

The big three1 seem to compile it OK, but I couldn't actually find a reference explaining that the lifetime of the temporary will be extended at least through the function call.


0 As it turns out, based on the answer by M.M below, part of my searching issues was because I was looking for information on temporaries, while the correct C term for this particular initialization construct is compound literal.

1 I should call it "the big cross-platform three" really, in deference to MSVC, but actually I really just mean "the C compilers godbolt supports".


Solution

  • (point_t){1, 2} is not a "temporary". It is a compound literal. (The same sequence of tokens in C++ has a different meaning, these two languages should not be confused with each other).

    A compound literal is an lvalue, so it is legal to use the unary & operator on it. The storage duration is covered by C11 6.5.2.5/5:

    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.

    So this code is correct, and the compound literal keeps existing until the end of the function it was declared in.