Что означает "int * a = (int [2]) {0, 2}; точно делаете?

Я был очень удивлен, когда увидел это обозначение. Что он делает и что такое понятие C?

Ответ 1

Это сложный литерал, определенный в разделе 6.5.2.5 стандарта C99.

Это не часть языка С++, поэтому неудивительно, что компиляторы С++ не компилируют его. (или компиляторы Java или Ada, если на то пошло)

Значение составного литерала - это имя неназванного объекта, инициализированного список инициализаторов. Если составной литерал происходит вне тела функции, объект имеет статическую продолжительность хранения; в противном случае он имеет автоматическую продолжительность хранения, связанную с закрывающий блок.

Нет, это не разрушит стек. Компилятор выделяет хранилище для объекта.

Скобки скопированы вокруг типа, и за ним следует список инициализаторов - это не листинг, так как список голых инициализаторов не имеет смысла в синтаксисе C99; вместо этого это постфиксный оператор, применяемый к типу, который дает объект данного типа. Вы не создаете { 0, 3 } и отбрасываете его в массив, вы инициализируете int[2] со значениями 0 и 3.


Что касается того, почему он используется, я не вижу достаточной причины для этого в вашей отдельной строке, хотя может быть, что можно переназначить, чтобы указать на какой-либо другой массив, и поэтому это более короткий способ сделать первый две строки:

int default_a[] = { 0, 2 };
int *a = default_a;

if (some_test) a = get_another_array();

Я нашел полезным использовать временные объединения для функций

// fills an array of unions with a value
kin_array_fill ( array, ( kin_variant_t ) { .ref = value } )

Ответ 2

Это конструкция c99, называемая составным литералом.

Из майского проекта 2005 года в разделе 6.5.2.5:

Постфиксное выражение, состоящее из имя в скобках, за которым следует скопированный список инициализаторов является составным литералом. Он обеспечивает неназванный объект, значение которого задается формулой список инициализаторов.

...

ПРИМЕР 1 Определение области файла

int *p = (int []){2, 4}; 

инициализирует p чтобы указать на первый элемент массив из двух целых чисел, первый из которых имеет значение два, а второе, четыре. Выражения в этом соединении литерал должен быть постоянным. Неименованный объект имеет статическое хранилище длительность.

Ответ 3

  • Выделяет в стеке пространство для [массива] двух int s.
  • Задает [массив] двух int значениями 0 и 2 соответственно.
  • Объявляет локальную переменную типа int* и присваивает этой переменной адрес [массива] двух int s.

Ответ 4

(int [2]) сообщает компилятору, что следующее выражение должно быть записано в int [2]. Это необходимо, так как {0, 2} может быть отлито для разных типов, например long [2]. Листинг происходит во время компиляции - не время выполнения.

Все выражение создает массив в памяти и устанавливает a для указания на этот массив.

Ответ 5

  • {0, 2} - это обозначение для массива, состоящего из 0 и 2.
  • (int[2]) выводит его в массив (не знаю почему).
  • int * a = присваивает его указателю int a.