Wie setzt Array [100] = {0} das gesamte Array auf 0?


140

Wie füllt der Compiler Werte aus char array[100] = {0};? Was ist die Magie dahinter?

Ich wollte wissen, wie der interne Compiler initialisiert wird.


1
In C oder C ++? Das sind zwei getrennte Fragen.
Toby Speight

Antworten:


163

Es ist keine Magie.

Das Verhalten dieses Codes in C wird in Abschnitt 6.7.8.21 der C-Spezifikation ( Online-Entwurf der C-Spezifikation ) beschrieben: Für die Elemente, die keinen angegebenen Wert haben, initialisiert der Compiler Zeiger auf NULL und arithmetische Typen auf Null ( und wendet dies rekursiv auf Aggregate an).

Das Verhalten dieses Codes in C ++ wird in Abschnitt 8.5.1.7 der C ++ - Spezifikation ( Online-Entwurf der C ++ - Spezifikation ) beschrieben: Das Compiler-Aggregat initialisiert die Elemente, die keinen bestimmten Wert haben.

Beachten Sie außerdem, dass Sie in C ++ (aber nicht in C) eine leere Initialisierungsliste verwenden können, wodurch der Compiler alle Elemente des Arrays aggregiert und initialisiert:

char array[100] = {};

Schauen Sie sich die folgende Frage an, welche Art von Code der Compiler dabei generieren könnte: Seltsame Assembly aus der Array-0-Initialisierung


Tun dies alle C-Compiler? Ich musste glauben, dass dies nur Visual Studio tut.
JFA

1
Online-Entwurf von C ++ - Spezifikationen defekt, hat jemand einen neuen Link?
Behrooz Karjoo

35

Die Implementierung liegt bei den Compiler-Entwicklern.

Wenn Ihre Frage lautet "Was passiert mit einer solchen Deklaration?", Setzt der Compiler das erste Array-Element auf den von Ihnen angegebenen Wert (0) und alle anderen werden auf Null gesetzt, da dies ein Standardwert für ausgelassene Array-Elemente ist.


Ich habe keine Quelle, bin mir aber ziemlich sicher, dass ich irgendwo gelesen habe, dass es keinen Standardwert für Array-Deklarationen gibt. Sie bekommen den Müll, der schon da war. Es macht keinen Sinn, Zeit damit zu verschwenden, diese Werte festzulegen, wenn Sie sie wahrscheinlich trotzdem überschreiben.
Ryan Fox

10
Ryan, wenn Sie keinen Wert für das erste Element festlegen, für das das gesamte Array nicht initialisiert ist und tatsächlich Müll enthält, aber wenn Sie einen Wert für mindestens ein Element festlegen, wird das gesamte Array initialisiert, sodass nicht angegebene Elemente implizit initialisiert werden 0.
qrdl

1
Für C ++ initialisiert eine leere Initialisierungsliste für ein begrenztes Array standardmäßig alle Elemente.
dalle

2
@ NatanYellin Wo habe ich gesagt, dass dies undefiniert ist? Bitte lesen Sie die vollständige Antwort, bevor Sie kommentieren und abstimmen.
Qrdl

1
@qrdl Du hast recht. Ich habe Ihren Kommentar zur Implementierung falsch verstanden. Leider kann ich meine Stimme jetzt nicht ändern.
Natan Yellin

27

Wenn Ihr Compiler GCC ist, können Sie auch die folgende Syntax verwenden:

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

Bitte schauen Sie unter http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html#Designated-Inits nach und beachten Sie, dass dies eine compilerspezifische Funktion ist.


Herzlich willkommen! Da Sie darum gebeten haben, mehr solche Tricks zu suchen, hatte ich
Lakshmanaraj

1
Sie können dies sicherlich tun, wenn Sie möchten, aber es gibt offensichtliche Nachteile, sich auf compilerspezifische Erweiterungen wie diese zu verlassen.
Dan Olson

@ Dan Olson seine Frage selbst stellt sich nach compilerspezifisch und hat dies daher gepostet. Wenn Sie der Meinung sind, dass es nutzlos ist, werde ich löschen.
Lakshmanaraj

5
Es ist nicht nutzlos, es ist interessant. Der Vorbehalt verdient nur Beachtung.
Dan Olson

2
Es ist so ein Zeug, dass ich immer wieder zu SO zurückkehre und mehr als die wenigen Antworten
lese

19

Es hängt davon ab, wo Sie diese Initialisierung platzieren.

Wenn das Array statisch ist wie in

char array[100] = {0};

int main(void)
{
...
}

dann ist es der Compiler, der die 100 0 Bytes im Datensegment des Programms reserviert. In diesem Fall hätten Sie den Initialisierer weglassen können.

Wenn Ihr Array automatisch ist, ist es eine andere Geschichte.

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

In diesem Fall haben Sie bei jedem Aufruf der Funktion foo ein verstecktes Memset.

Der obige Code entspricht

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

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

und wenn Sie den Initialisierer weglassen, enthält Ihr Array zufällige Daten (die Daten des Stapels).

Wenn Ihr lokales Array wie in statisch deklariert ist

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

dann ist es technisch der gleiche Fall wie beim ersten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.