как array [100] = {0} устанавливает для всего массива значение 0?

140

Как компилятор заполняет значения char array[100] = {0};? Что за магия стоит за этим?

Я хотел знать, как инициализируется внутренний компилятор.

Намрата Патил
источник
1
На C или C ++? Это два разных вопроса.
Тоби Спейт

Ответы:

164

Это не волшебство.

Поведение этого кода на языке C описано в разделе 6.7.8.21 спецификации C ( онлайн-проект спецификации C ): для элементов, не имеющих указанного значения, компилятор инициализирует указатели на NULL, а арифметические типы - на ноль ( и рекурсивно применяет это к агрегатам).

Поведение этого кода в C ++ описано в разделе 8.5.1.7 спецификации C ++ ( онлайн-проект спецификации C ++ ): компилятор агрегатно инициализирует элементы, для которых нет указанного значения.

Также обратите внимание, что в C ++ (но не в C) вы можете использовать пустой список инициализаторов, заставляя компилятор агрегировать-инициализировать все элементы массива:

char array[100] = {};

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

bk1e
источник
Все ли компиляторы C делают это? Меня заставили поверить, что это делает только Visual Studio.
JFA
1
онлайн-черновик спецификаций c ++ сломан, у кого-нибудь есть новая ссылка?
Behrooz Karjoo 02
35

Реализация зависит от разработчиков компилятора.

Если ваш вопрос - «что произойдет с таким объявлением» - компилятор установит для первого элемента массива значение, которое вы указали (0), а все остальные будут установлены в ноль, поскольку это значение по умолчанию для пропущенных элементов массива.

qrdl
источник
У меня нет источника, но я почти уверен, что где-то читал, что не существует значения по умолчанию для объявлений массивов; вы получаете тот мусор, который уже был там. Нет смысла тратить время на установку этих значений, если вы все равно можете их перезаписать.
Райан Фокс,
10
Райан, если вы не установите значение для первого элемента, что весь массив не инициализирован и действительно содержит мусор, но если вы установите значение хотя бы для одного его элемента, весь массив станет инициализированным, поэтому неуказанные элементы инициализируются неявно, чтобы 0.
qrdl
1
Для C ++ пустой список инициализаторов для ограниченного массива по умолчанию инициализирует все элементы.
далле
2
@NatanYellin Где я сказал, что это не определено? Пожалуйста, прочтите полный ответ, прежде чем комментировать и голосовать против.
qrdl 02
1
@qrdl Вы правы. Я неправильно понял ваш комментарий о реализации. К сожалению, сейчас я не могу изменить свой голос.
Натан Йеллин
27

Если ваш компилятор - GCC, вы также можете использовать следующий синтаксис:

int array[256] = {[0 ... 255] = 0};

См. Http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html#Designated-Inits и обратите внимание, что это особенность компилятора .

лакшманарадж
источник
Добро пожаловать! раз уж вы просили
поискать
1
Вы, конечно, можете сделать это, если захотите, но есть очевидные недостатки в использовании таких специфичных для компилятора расширений, как это.
Дэн Олсон,
@Dan Olson сам задает вопрос о компиляторе и, следовательно, опубликовал это. Если посчитаете, что это бесполезно, удалю.
lakshmanaraj
5
Это не бесполезно, это интересно. Это предостережение заслуживает упоминания.
Дэн Олсон,
2
Подобные
19

Это зависит от того, где вы разместите эту инициализацию.

Если массив статический, как в

char array[100] = {0};

int main(void)
{
...
}

тогда именно компилятор резервирует 100 0 байтов в сегменте данных программы. В этом случае вы могли пропустить инициализатор.

Если ваш массив автоматический, то это отдельная история.

int foo(void)
{
char array[100] = {0};
...
}

В этом случае при каждом вызове функции foo у вас будет скрытый memset.

Приведенный выше код эквивалентен

int foo(void)
{ 
char array[100];

memset(array, 0, sizeof(array));
....
}

и если вы опустите инициализатор, ваш массив будет содержать случайные данные (данные стека).

Если ваш локальный массив объявлен статическим, как в

int foo(void)
{ 
static char array[100] = {0};
...
}

то технически это тот же случай, что и первый.

LP
источник