як масив [100] = {0} встановлює весь масив на 0?


140

Як компілятор заповнює значення char array[100] = {0};? У чому магія за цим?

Мені хотілося знати, як ініціалізується внутрішньо компілятор.


1
В С або С ++? Вони є двома окремими питаннями.
Toby Speight

Відповіді:


163

Це не магія.

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

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

Також зауважте, що в C ++ (але не на C) ви можете використовувати порожній список ініціалізатора, змушуючи компілятор агрегувати-ініціалізувати всі елементи масиву:

char array[100] = {};

Що стосується того, який код може створювати компілятор, роблячи це, погляньте на це питання: Дивна збірка з масиву 0-ініціалізація


Чи роблять це всі компілятори C? Мене повірили, що це робить лише Visual Studio.
JFA

1
зламана онлайн-версія специфікацій c ++, хтось має нове посилання?
Behrooz Karjoo

35

Реалізація залежить від розробників-компіляторів.

Якщо у вас запитання "що буде з такою декларацією", компілятор встановить для першого елемента масиву значення, яке ви вказали (0), а всі інші встановлять на нуль, оскільки це значення за замовчуванням для опущених елементів масиву.


У мене немає джерела, але я впевнений, що десь прочитав, що для декларацій масиву немає значення за замовчуванням; ви отримуєте те, що сміття там уже було. Даремно витрачати час на встановлення цих значень, немає сенсу, коли ви все одно перезапишете їх.
Райан Фокс

10
Райан, якщо ви не встановите значення для першого елемента, що весь масив неініціалізований і дійсно містить сміття, але якщо ви встановите значення принаймні для одного елемента його, весь масив стає ініціалізованим, тому не визначені елементи ініціалізуються неявно в 0.
qrdl

1
Для C ++ порожній список ініціалізатора для обмеженого масиву за замовчуванням - ініціалізує всі елементи.
Далле

2
@NatanYellin Де я сказав, що це не визначено? Будь ласка, прочитайте повну відповідь, перш ніж коментувати та відхиляти.
qrdl

1
@qrdl Ви маєте рацію. Я неправильно зрозумів ваш коментар щодо реалізації. На жаль, зараз я не можу змінити свій голос.
Натан Єллін

27

Якщо ваш компілятор GCC, ви також можете використовувати наступний синтаксис:

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

Погляньте на сторінку http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designized-Inits.html#Designized-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 у вас з'явиться прихована пам’ятка.

Код, наведений вище, еквівалентний

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

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

і якщо ви опустите ініціалізатор, ваш масив буде містити випадкові дані (дані стека).

Якщо ваш локальний масив оголошений статичним, як в

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

тоді це технічно той самий випадок, що і перший.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.