Spec-Zone.ru › GCC 4

6.25 Составные литералы

ISO C99 поддерживает составные литералы. Составный литерал выглядит как приведение с инициализатором. Его значение — это объект указанного в приведении типа, содержащий элементы, указанные в инициализаторе; это lvalue. В качестве расширения GCC поддерживает составные литералы в режиме C90 и в C++, хотя семантика несколько отличается в C++.

Обычно указанный тип — это структура. Предположим, что struct foo и structure объявлены так:

struct foo {int a; char b[2];} structure;

Вот пример создания struct foo с помощью составного литерала:

structure = ((struct foo) {x + y, 'a', 0});

Это эквивалентно написанию следующего:

{
  struct foo temp = {x + y, 'a', 0};
  structure = temp;
}

Вы также можете создать массив, хотя это опасно в C++, как объяснено ниже. Если все элементы составного литерала являются (состоят из) простых константных выражений, подходящих для использования в инициализаторах объектов со статической продолжительностью жизни, то составной литерал можно привести к указателю на его первый элемент и использовать в такой инициализации, как показано здесь:

char **foo = (char *[]) { "x", "y", "z" };

Составные литералы для скалярных типов и типов объединений также разрешены, но тогда составной литерал эквивалентен приведению.

В качестве расширения GNU, GCC разрешает инициализацию объектов со статической продолжительностью жизни составными литералами (что невозможно в ISO C99, потому что инициализатор не является константой). Это обрабатывается так, как если бы объект был инициализирован только списком в квадратных скобках, если типы составного литерала и объекта совпадают. Список инициализаторов составного литерала должен быть константой. Если инициализируемый объект имеет тип массива неизвестного размера, размер определяется размером составного литерала.

static struct foo x = (struct foo) {1, 'a', 'b'};
static int y[] = (int []) {1, 2, 3};
static int z[] = (int [3]) {1};

Вышеприведенные строки эквивалентны следующему:

static struct foo x = {1, 'a', 'b'};
static int y[] = {1, 2, 3};
static int z[] = {1, 0, 0};

В C, составной литерал обозначает неопределенный объект со статической или автоматической продолжительностью жизни. В C++, составной литерал обозначает временный объект, который существует только до конца своего полного выражения. В результате корректный код C, берущий адрес подобъекта составного литерала, может быть некорректным в C++. Например, если пример составного литерала массива выше появляется внутри функции, любое последующее использование ‘foo’ в C++ имеет неопределенное поведение, потому что продолжительность жизни массива заканчивается после объявления ‘foo’. В результате компилятор C++ теперь отклоняет преобразование временного массива в указатель.

В целях оптимизации, компилятор C++ иногда дает составным литералам массивов более длительную продолжительность жизни: когда массив появляется вне функции или имеет тип с модификатором const. Если ‘foo’ и его инициализатор имели элементы типа ‘char *const’ вместо ‘char *’, или если ‘foo’ была глобальной переменной, массив имел бы статическую продолжительность жизни. Но, вероятно, лучше всего просто избегать использования составных литералов массивов в коде, компилируемом как C++.

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Compound-Literals.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API