Взятие адреса временного (составного литерала) параметра в 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:
Если составной литерал происходит вне тела функции, объект имеет статическую продолжительность хранения; в противном случае, она имеет автоматическая продолжительность хранения, связанная с заключительным блоком.
таким образом, этот код верен, и составной литерал продолжает существовать до конца функции, в которой он был объявлен.