Разница между "int arr [] = {}" и "int arr []" в C - PullRequest
4 голосов
/ 27 марта 2020

Посмотрите следующий код:

int arr[4];
for (int index = 0; index < 4; ++index) {
    printf("%d\t", arr[index]);
}

Он печатает случайные значения, например так:

27224   -6784   32766   0   

Но когда я устанавливаю arr в {}, он печатает нули вместо этого.

int arr[4] = {};
for (int index = 0; index < 4; ++index) {
    printf("%d\t", arr[index]);
}
0   0   0   0   

Почему?

Ответы [ 5 ]

8 голосов
/ 27 марта 2020

По умолчанию элементы массива неинициализированы, что означает, что они будут содержать значения мусора:

int arr[4];

Используя инициализатор с фигурными скобками, вы можете установить начальные значения явно, например,

int arr[4] = {1, 2, 3, 4};

Но если число чисел в фигурных скобках меньше длины массива, остальные заполняются нулями. Вот что происходит в этом случае:

int arr[4] = {};

Обратите внимание, что это недопустимо в C, только в C ++, но ваш компилятор, очевидно, разрешает это в любом случае. В стандарте C необходимо указать хотя бы одно значение:

int arr[4] = {0};
4 голосов
/ 27 марта 2020

Когда я пробую ваш код в моем компиляторе (g cc 9.3), он выдает следующее предупреждение:

prog_c.c:14:12: warning: ISO C forbids empty initializer braces [-Wpedantic]
   14 | int arr[4]={};

Я думаю, что он считает, что это эквивалентно int arr[4]={a_single_value};, но без это единственное значение (которое неверно).
Когда вы предоставляете начальное значение для меньшего количества элементов, чем общее количество элементов в массиве, тогда язык считает, что недостающие элементы установлены в ноль.
В вашем неверный случай, я думаю, компилятор применяет одно и то же правило ко всем элементам.
Ваша {} инициализация рассматривается как частичная инициализация массива.

2 голосов
/ 27 марта 2020

Оба фрагмента кода недопустимы.

В первом фрагменте кода массив имеет автоматическую c продолжительность хранения и не инициализируется. Поэтому его элементы имеют неопределенные значения. В результате программа имеет неопределенное поведение.

Во втором фрагменте кода используется недопустимая конструкция для инициализации массива

int arr[4] = {};

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

int arr[4] = { 0 };

Когда инициализируется меньше, чем количество инициализированных элементов, элементы, не имеющие явных инициализаторов, инициализируются нулями.

Из C Стандарт (6.7.9 Инициализация)

21 Если в списке в скобках меньше инициализаторов, чем элементов или элементов агрегата или меньше символов в строковом литерале, используемом для инициализации массива известного размера, чем элементы в массиве, оставшаяся часть агрегата должна быть неявно инициализирована так же, как и объекты, которые имеют c продолжительность хранения.

и

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

- если он имеет тип указателя, он инициализируется нулевым указателем;

- если он имеет арифметику * Тип 1055 *, он инициализируется нулем (положительным или без знака);

- если это агрегат, каждый элемент инициализируется (рекурсивно) в соответствии с этими правилами, а любое заполнение инициализируется нулевыми битами;

- если это объединение, первый именованный элемент инициализируется (рекурсивно) в соответствии с этими правилами, а любое заполнение инициализируется нулевыми битами;

Итак, в этом объявлении первый элемент массива инициализируется явно 0, а все остальные элементы массива инициализируются неявно компилятором с 0.

В C такая инициализация

int arr[4] = { 0 };

эквивалентна следующая форма инициализации

int arr[4] = { [0] = 0 };

или, например, следующая форма

int arr[4] = { [3] = 0 };

, или вы даже можете опустить номер элемента вводится в объявление массива как, например,

int arr[] = { [3] = 0 };

То есть все элементы, которые не имеют явного инициализатора, будут инициализироваться нулями.

0 голосов
/ 27 марта 2020

Просто объявив int arr [4], вы просто создаете ссылку. Поскольку ему никогда не присваивается значение, значения, на которые указывает эта ссылка, не изменяются. Это потому, что C является явным языком. Таким образом, значения - это значения того, что ранее использовалось в памяти, используемой arr [4].

Объявляя int arr[4] = {};, вы явно устанавливаете свой массив равным чему-либо. Это очищает память, на которую вы ссылаетесь с помощью arr [4], и устанавливает ее равной значению {}. Поскольку {} не содержит никаких значений, C ++ по умолчанию имеет значение 0.

Похоже, у вас работает IDE, которая может компилировать C и код C ++. Вот почему по умолчанию это значение равно 0. C более явно, чем в C ++, поэтому для кода C вы должны поместить значения в скобки, например,
int arr[4] = {1, 2, 3, 4};

Надеюсь, что это поможет!

0 голосов
/ 27 марта 2020

Код

int arr[4];

выделяет память для массива из четырех дюймов (в стеке), но не инициализирует ее. Вывод, который вы получаете, представляет собой просто представление того, что произошло в памяти - фактически случайное.

int arr[4] = {}

инструктирует компилятору установить все значения на ноль.

Альтернативно вы можете поместить

int arr[4]  = {1,2,3,4}

Инициализировать для указания c значений

...