Взятие адреса временного (составного литерала) параметра в C

Я не могу себе представить, что это еще не дубликат, но я не могу легко найти ответ, так как более сложные сценарии специально для C++, похоже, доминируют в обсуждении0.

законно ли брать адрес временного построенного в списке параметров вызова функции в C99?

например, что-то вроде init_list или init_desig_init следующим образом:

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});
}

большой тройки1кажется, скомпилировать его OK, но я не мог найти ссылку, объясняющую, что время жизни временного будет продлено, по крайней мере, через вызов функции.


0 как оказалось, на основе ответа по М. М ниже, часть моих проблем с поиском была потому, что я искал информацию о Вэнс, в то время как правильный термин C для этой конкретной конструкции инициализации -соединение литерал.

1 Я должен назвать его "большой кросс-платформенной тройкой" действительно, в знак уважения к MSVC, но на самом деле я просто имею в виду "компиляторы C, поддерживаемые godbolt".

1 ответов


(point_t){1, 2} не является "временным". Это сложный литерал. (Одна и та же последовательность токенов в C++ имеет разное значение, эти два языка не следует путать друг с другом).

составной литерал является lvalue, поэтому законно использовать унарный & оператор на нем. Продолжительность хранения покрывается C11 6.5.2.5 / 5:

Если составной литерал происходит вне тела функции, объект имеет статическую продолжительность хранения; в противном случае, она имеет автоматическая продолжительность хранения, связанная с заключительным блоком.

таким образом, этот код верен, и составной литерал продолжает существовать до конца функции, в которой он был объявлен.