C Language
Составные литералы
Поиск…
Синтаксис
- (тип) {initializer-list}
замечания
Стандарт C говорит в C11-§6.5.2.5 / 3:
Постфиксное выражение, состоящее из имени типа в скобках, за которым следует скопированный список инициализаторов, является сложным литералом . Он предоставляет неназванный объект, значение которого задается в списке инициализаторов. 99)
и сноска 99 гласит:
Обратите внимание, что это отличается от литого выражения. Например, приведение задает преобразование только в скалярные типы или только void , а результат литого выражения не является значением lvalue.
Обратите внимание, что:
Строковые литералы и составные литералы с категориальными типами, не обязательно обозначают разные объекты. 101)
101). Это позволяет реализациям совместно использовать хранилище для строковых литералов и постоянных составных литералов с одинаковыми или перекрывающимися представлениями.
Пример приведен в стандарте:
С11-§6.5.2.5 / 13:
Подобно строковым литералам, const-квалифицированные составные литералы могут быть помещены в постоянную память и могут быть разделены. Например,
(const char []){"abc"} == "abc"
может дать 1, если хранилище литералов разделено.
Определение / Инициализация сложных литералов
Комбинированный литерал является неназванным объектом, который создается в области, где определено. Концепция была впервые введена в стандарте C99. Примером для составного литерала является
Примеры из стандарта C, C11-§6.5.2.5 / 9:
int *p = (int [2]){ 2, 4 };
p
инициализируется адресом первого элемента неназванного массива из двух целых чисел.
Смежный литерал - это значение lvalue. Длительность хранения неназванного объекта является либо статической (если литерал появляется в области файла), либо автоматически (если литерал появляется в области блока), а в последнем случае время жизни объекта заканчивается, когда элемент управления выходит из закрывающего блока.
void f(void) { int *p; /*...*/ p = (int [2]){ *p }; /*...*/ }
p
присваивается адрес первого элемента массива из двух ints, первый из которых имеет значение, ранее указанноеp
а второе - ноль. [...]
Здесь p
остается действительным до конца блока.
Комбинированный литерал с указателями
(также от C11)
struct point {
unsigned x;
unsigned y;
};
extern void drawline(struct point, struct point);
// used somewhere like this
drawline((struct point){.x=1, .y=1}, (struct point){.x=3, .y=4});
drawline
функция drawline
получает два аргумента типа struct point
. Первый имеет координаты x == 1
и y == 1
, тогда как второй имеет x == 3
и y == 4
Составной литерал без указания длины массива
int *p = (int []){ 1, 2, 3};
В этом случае размер массива не указан, тогда он будет определяться длиной инициализатора.
Составной литерал, имеющий длину инициализатора меньше указанного размера массива
int *p = (int [10]){1, 2, 3};
остальные элементы составного литерала будут инициализированы до 0
неявно.
Только для чтения составной литерал
Обратите внимание, что составной литерал является lvalue, и поэтому его элементы могут быть модифицируемыми. Литерал соединения только для чтения может быть указан с использованием спецификатора const
as (const int[]){1,2}
.
Комбинированный литерал, содержащий произвольные выражения
Внутри функции составной литерал, как и для любой инициализации с C99, может иметь произвольные выражения.
void foo()
{
int *p;
int i = 2; j = 5;
/*...*/
p = (int [2]){ i+j, i*j };
/*...*/
}