C - Создание анонимного экземпляра структуры
В этом коде структура определяется следующим образом:
typedef struct
{
int line;
int column;
} Pos;
И позже использовал этот способ:
Pos get_pos ( int delta )
{
...
return ( Pos ){ f->line, f->column + delta };
}
Линия, return ( Pos ){ f->line, f->column + delta }
кажется, создает анонимный экземпляр структуры Pos
с инициализированными значениями. Как называется эта техника и как она работает? Где я могу узнать больше об этом?
1 ответ
Это называется составным литералом и задокументировано в разделе 6.5.2.5 стандарта C.
Вот выдержка из этого раздела:
3 Постфиксное выражение, которое состоит из имени типа в скобках, за которым следует заключенный в скобки список инициализаторов, является составным литералом. Он предоставляет неназванный объект, значение которого задается списком инициализатора.
4 Если имя типа задает массив неизвестного размера, размер определяется списком инициализатора, как указано в 6.7.9, и тип составного литерала - это тип завершенного массива. В противном случае (когда имя типа указывает тип объекта), тип составного литерала соответствует типу, указанному в имени типа. В любом случае результатом является lvalue.
5 Значение составного литерала - это значение безымянного объекта, инициализированного списком инициализатора. Если составной литерал находится вне тела функции, объект имеет статическую продолжительность хранения; в противном случае он имеет автоматическую продолжительность хранения, связанную с окружающим блоком.
В вашем случае составной литерал для struct
, но они могут быть созданы и для массивов. Параграф 8 дает пример:
8 ПРИМЕР 1 Определение области файла
int *p = (int []){2, 4};
инициализирует
p
указывать на первый элемент массива из двух целых, первый из которых имеет значение два, а второй - четыре. Выражения в этом составном литерале должны быть постоянными. Безымянный объект имеет статическую продолжительность хранения.
Также обратите внимание, что составной литерал является lvalue, что означает, что вы можете взять его адрес:
Pos *p = &( Pos ){ f->line, f->column + delta };
Этот объект имеет время жизни, связанное с его областью, что означает, что, как только область действия заканчивается, объект больше не существует. Так что не носите его адрес после того, как он выходит из области видимости.
Вы также можете использовать составной литерал с указанным инициализатором:
return ( Pos ){ .line=f->line, .column=f->column + delta };