Что значит "int * a = (int [2]) {0, 2};"точно делать? - PullRequest
10 голосов
/ 11 июня 2010

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

Ответы [ 5 ]

19 голосов
/ 11 июня 2010

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

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

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

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

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


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

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

if (some_test) a = get_another_array();

I 'Мы нашли это полезным для передачи временных объединений в функции

// fills an array of unions with a value
kin_array_fill ( array, ( kin_variant_t ) { .ref = value } )
6 голосов
/ 11 июня 2010

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

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

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

...

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

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

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

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

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

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

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