w jaki sposób tablica [100] = {0} ustawia całą tablicę na 0?

140

W jaki sposób kompilator wypełnia wartości char array[100] = {0};? Jaka magia się za tym kryje?

Chciałem wiedzieć, jak inicjuje się wewnętrznie kompilator.

Namratha Patil
źródło
1
W C czy C ++? To dwa oddzielne pytania.
Toby Speight

Odpowiedzi:

163

To nie jest magia.

Zachowanie tego kodu w C jest opisane w sekcji 6.7.8.21 specyfikacji C ( wersja robocza specyfikacji C online ): dla elementów, które nie mają określonej wartości, kompilator inicjalizuje wskaźniki na NULL i typy arytmetyczne na zero ( i rekurencyjnie stosuje to do agregatów).

Zachowanie tego kodu w C ++ jest opisane w sekcji 8.5.1.7 specyfikacji C ++ ( wersja robocza specyfikacji C ++ w trybie online ): kompilator agreguje-inicjuje elementy, które nie mają określonej wartości.

Zwróć też uwagę, że w C ++ (ale nie w C) możesz użyć pustej listy inicjalizującej, co spowoduje, że kompilator będzie agregował i inicjował wszystkie elementy tablicy:

char array[100] = {};

Jeśli chodzi o rodzaj kodu, który kompilator może wygenerować, gdy to zrobisz, spójrz na to pytanie: Dziwny zestaw z tablicy 0-inicjalizacja

bk1e
źródło
Czy wszystkie kompilatory C to robią? Doszedłem do wniosku, że robi to tylko Visual Studio.
JFA
1
wersja robocza specyfikacji C ++ online jest uszkodzona, ktoś ma nowy link?
Behrooz Karjoo
35

Implementacja należy do programistów kompilatorów.

Jeśli twoje pytanie brzmi "co się stanie z taką deklaracją" - kompilator ustawi pierwszy element tablicy na wartość, którą podałeś (0), a wszystkie pozostałe na zero, ponieważ jest to wartość domyślna dla pominiętych elementów tablicy.

qrdl
źródło
Nie mam źródła, ale jestem prawie pewien, że gdzieś przeczytałem, że nie ma wartości domyślnej dla deklaracji tablicowych; dostajesz wszystkie śmieci, które już tam były. Nie ma sensu tracić czasu na ustawianie tych wartości, jeśli i tak prawdopodobnie je zastąpisz.
Ryan Fox
10
Ryan, jeśli nie ustawisz wartości dla pierwszego elementu, że cała tablica jest niezainicjalizowana i rzeczywiście zawiera śmieci, ale jeśli ustawisz wartość dla co najmniej jednego elementu, cała tablica zostanie zainicjalizowana, więc nieokreślone elementy zostaną zainicjowane niejawnie 0.
qrdl
1
W przypadku C ++ pusta lista inicjatorów dla ograniczonej tablicy domyślnie inicjuje wszystkie elementy.
dalle
2
@NatanYellin Gdzie powiedziałem, że to jest nieokreślone? Przeczytaj pełną odpowiedź przed skomentowaniem i odrzuceniem głosów.
qrdl
1
@qrdl Masz rację. Źle zrozumiałem Twój komentarz dotyczący implementacji. Niestety nie mogę teraz zmienić swojego głosu.
Natan Yellin
27

Jeśli Twój kompilator to GCC, możesz również użyć następującej składni:

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

Proszę spojrzeć na http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html#Designated-Inits i zauważyć, że jest to funkcja specyficzna dla kompilatora .

lakshmanaraj
źródło
Witamy! ponieważ prosiłeś o szukanie więcej takich sztuczek,
podałem
1
Z pewnością możesz to zrobić, jeśli wybierzesz, ale poleganie na rozszerzeniach specyficznych dla kompilatora, takich jak to, ma oczywiste wady.
Dan Olson
@Dan Olson sam pyta o konkretny kompilator i dlatego opublikował to. Jeśli uznasz, że jest bezużyteczny, usunę.
lakshmanaraj
5
To nie jest bezużyteczne, to interesujące. Zastrzeżenie to zasługuje na uwagę.
Dan Olson
2
To takie rzeczy sprawiają, że wracam do SO i czytam więcej niż kilka najpopularniejszych odpowiedzi ...
timday
19

To zależy, gdzie umieścisz tę inicjalizację.

Jeśli tablica jest statyczna, jak w

char array[100] = {0};

int main(void)
{
...
}

wtedy to kompilator rezerwuje 100 0 bajtów w segmencie danych programu. W takim przypadku mogłeś pominąć inicjalizator.

Jeśli twoja tablica jest automatyczna, to inna historia.

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

W takim przypadku przy każdym wywołaniu funkcji foo będziesz mieć ukryty zestaw pamięci.

Powyższy kod jest równoważny z

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

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

a jeśli pominiesz inicjalizator, twoja tablica będzie zawierała losowe dane (dane stosu).

Jeśli twoja lokalna tablica jest zadeklarowana jako statyczna, jak w

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

to jest technicznie ten sam przypadek, co pierwszy.

Płyty LP
źródło