як масив [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.