Spec-Zone.ru › GCC 11

Следующая: Определённые инициализаторы, Предыдущая: Непостоянные инициализаторы, Вверх: Расширения семейства языков C [Оглавление][Индекс]

6.28 Комбинированные литералы ¶

Комбинированный литерал выглядит как приведение к типу скобочной агрегированной инициализационной последовательности. Его значение — это объект указанного в приведении типа, содержащий элементы, указанные в инициализаторе. В отличие от результата приведения, комбинированный литерал — это lvalue. ISO C99 и более поздние версии поддерживают комбинированные литералы. В качестве расширения 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" };

Комбинированные литералы для скалярных типов и типов объединений также разрешены. В следующем примере переменная i инициализируется значением 2, результатом инкрементирования безымянного объекта, созданного комбинированным литералом.

int i = ++(int) { 1 };

В качестве расширения 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++, поэтому G++ отказывается от преобразования временного массива в указатель. Например, если пример массива комбинированного литерала выше появлялся внутри функции, любое последующее использование foo в C++ имело бы неопределённое поведение, потому что время жизни массива заканчивается после объявления foo.

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

Следующая: Определённые инициализаторы, Предыдущая: Непостоянные инициализаторы, Вверх: Расширения семейства языков C [Оглавление][Индекс]

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

Spec-Zone.ru

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