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.


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


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.


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 .


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.