Was ist der Anfangswert der ganzen Zahlen? Ich erhalte unterschiedliche Ergebnisse mit verschiedenen Compilern und möchte wissen, ob es etwas mit dem Compiler oder dem Betriebssystem zu tun hat.
Khaled Alshaya
Wenn das Array in einer Funktion deklariert ist, ist der Wert undefiniert. int x[10]; in einer Funktion bedeutet: den Besitz eines 10-int-großen Speicherbereichs übernehmen, ohne eine Initialisierung durchzuführen. Wenn das Array als global oder als deklariert ist static in einer Funktion werden alle Elemente auf Null initialisiert, wenn sie nicht bereits initialisiert sind.
Korrekt. Wenn es nicht global ist, enthält es den zufälligen Müll, der sich zuvor in diesem Speicherklumpen befand. Hat nichts mit dem Compiler zu tun. Wenn Sie etwas Bestimmtes darin haben wollen, legen Sie es dort hin.
– JasonWoof
12. September 2009 um 3:52 Uhr
@buzali Einige Compiler/Toolchains setzen Variablen und zugewiesenen Speicher immer auf Null, meistens, wenn Sie im “Debug” -Modus bauen (keine Optimierungen aktiviert). Dies dient normalerweise dazu, eine deterministische Debugging-Umgebung zu erstellen, wenn Sie beim Prototyping von Code vergessen, eine Variable zu initialisieren. Die andere Möglichkeit ist, dass der Speicher, den das Array verwendet, zufällig Nullen enthält.
– Drakonit
12. September 2009 um 4:16 Uhr
Falsch. Der Gültigkeitsbereich der Variablen spielt keine Rolle – die Speicherklasse schon.
– qrdl
12. September 2009 um 6:07 Uhr
@buzali: nein, das willst du nicht. Wenn Sie das Array mit Nullen initialisieren möchten, schreiben Sie int array[10] = {0};. Den Compiler dazu zu bringen, dies automatisch zu tun, bedeutet lediglich, dass Sie Code schreiben, der nur im Debug-Modus funktioniert und beim Freigeben abbricht oder von jemand anderem mit anderen Optionen kompiliert wird.
– Steve Jessop
12. September 2009 um 13:08 Uhr
@AraK: Es kann sich auch lohnen, Ihrer Antwort hinzuzufügen, dass a static Die innerhalb einer Funktion definierte Variable wird ebenfalls mit Nullen initialisiert.
– Steve Melnikoff
12. September 2009 um 16:04 Uhr
Standardmäßig werden alle globalen und funktionsstatischen Variablen automatisch auf 0 initialisiert. Automatische Variablen werden nicht initialisiert.
int a[10]; // global - all elements are initialised to 0
void foo(void) {
int b[10]; // automatic storage - contain junk
static int c[10]; // static - initialised to 0
}
Es empfiehlt sich jedoch, die Funktionsvariable unabhängig von ihrer Speicherklasse immer manuell zu initialisieren. Um alle Array-Elemente auf 0 zu setzen, müssen Sie nur das erste Array-Element auf 0 zuweisen – ausgelassene Elemente werden automatisch auf 0 gesetzt:
int b[10] = {0};
Um pedantisch zu sein, Dateibereichsvariablen (Globals) haben eine statische Speicherklasse, weshalb sie auf 0 initialisiert werden.
– Johannes Bode
12. September 2009 um 14:23 Uhr
@John Ja, aber weil statisch auf Dateiebene eine andere Bedeutung hat, habe ich es einfach “global” genannt, sei es dateiglobal oder programmglobal
– qrdl
12. September 2009 um 15:34 Uhr
Ich verstehe nicht, warum es sinnvoll ist, Zyklen beim Initialisieren eines großen Puffers zu verschwenden, den Sie in der nächsten Zeile mit Daten aus einer Datei/einem Netzwerk laden werden.
– Martin Jakob
28. Juli 2014 um 19:33 Uhr
DigitalRoss
Warum sind Funktionslokale (auto Speicherklasse) nicht initialisiert, wenn alles andere ist?
C ist nahe an der Hardware; das ist seine größte Stärke und seine größte Gefahr. Der Grund auto Speicherklassenobjekte haben zufällige Anfangswerte, weil sie auf dem Stapel zugewiesen werden und eine Entwurfsentscheidung getroffen wurde, diese nicht automatisch zu löschen (teilweise, weil sie bei jedem Funktionsaufruf gelöscht werden müssten).
Andererseits sind die Nicht-auto Objekte müssen nur einmal geräumt werden. Außerdem muss das Betriebssystem zugewiesene Seiten aus Sicherheitsgründen ohnehin löschen. Die Entwurfsentscheidung bestand hier also darin, die Nullinitialisierung anzugeben. Warum ist die Sicherheit beim Stack nicht auch ein Thema? Eigentlich ist es erstmal geräumt. Der Müll, den Sie sehen, stammt von früheren Instanzen der Aufrufrahmen Ihres eigenen Programms und dem von ihnen aufgerufenen Bibliothekscode.
Das Endergebnis ist schneller, speichereffizienter Code. Alle Vorteile der Montage ohne Schmerzen. Bevor dmr C erfand, wurden “HLL”s wie Basic und ganze OS-Kernel wirklich, buchstäblich, als riesige Assembler-Programme implementiert. (Mit bestimmten Ausnahmen an Orten wie IBM.)
Das ist meine Lieblingsantwort. Dies ist eine sehr gute, klare und prägnante Beschreibung, warum unterschiedliche Designentscheidungen für unterschiedliche Speicherklassen getroffen werden.
– Po-wei Huang
21. Mai um 12:59 Uhr
Gemäß der C-Norm, 6.7.8 (Anmerkung 10):
Wenn ein Objekt mit automatischer Speicherdauer nicht explizit initialisiert wird, ist sein Wert unbestimmt.
Es kommt also auf den Compiler an. Mit MSVC initialisieren Debug-Builds automatische Variablen mit 0xcc, während Nicht-Debug-Builds diese Variablen überhaupt nicht initialisieren.
Zan Luchs
Die AC-Variablendeklaration weist den Compiler lediglich an, einen Speicherbereich für Sie zu reservieren und zu benennen. Bei automatischen Variablen, auch Stack-Variablen genannt, werden die Werte in diesem Speicher gegenüber dem vorherigen nicht geändert. Globale und statische Variablen werden beim Programmstart auf Null gesetzt.
Einige Compiler im nicht optimierten Debug-Modus setzen automatische Variablen auf Null. Bei neueren Compilern ist es jedoch üblich geworden, die Werte auf einen bekannten schlechten Wert zu setzen, damit der Programmierer nicht unwissentlich Code schreibt, der davon abhängt, dass eine Null gesetzt wird.
Um den Compiler zu bitten, ein Array für Sie auf Null zu setzen, können Sie es wie folgt schreiben:
int array[10] = {0};
Noch besser ist es, das Array mit den Werten zu setzen, die es haben sollte. Das ist effizienter und vermeidet das doppelte Schreiben in das Array.
Wissen Sie, wie Sie dem Compiler sagen können, dass er die Werte auf Null setzen soll?? Ich verwende GCC … gibt es einen Debug-Parameter, der dies tut?
– Busali
12. September 2009 um 4:24 Uhr
Verlassen Sie sich nicht auf den Compiler, um das Array zu initialisieren, verwenden Sie einen expliziten Initialisierer, wie Zan vorschlägt. Selbst wenn der aktuelle gcc Arrays in einem Debug-Modus auf Null setzt, kann der nächste entscheiden, sie mit einem völlig anderen Wert zu füllen, was Sie in 5 Jahren mit einem sehr schwer zu lokalisierenden Fehler zurücklässt. Geben Sie einfach die zusätzlichen 5 Zeichen ein und verwenden Sie das int-Array[10] = {0};
– Sonnenfinsternis
12. September 2009 um 4:43 Uhr
Offensichtlich falsch. Variablen aus dem Datensegment werden immer genullt.
– qrdl
12. September 2009 um 6:10 Uhr
weit nicht immer genullt
– Benutzer3063349
12. September 2017 um 13:46 Uhr
In den meisten neuesten Compilern (z. B. gcc/vc++) werden teilweise initialisierte lokale Array-/Strukturmitglieder standardmäßig auf null (int), NULL (char/char-String), 0,000000 (float/double) initialisiert.
Abgesehen von lokalen Array-/Strukturdaten wie oben behalten auch statische (global/lokal) und globale Raummitglieder dieselbe Eigenschaft bei.
int a[5] = {0,1,2};
printf("%d %d %d\n",*a, *(a+2), *(a+4));
struct s1
{
int i1;
int i2;
int i3;
char c;
char str[5];
};
struct s1 s11 = {1};
printf("%d %d %d %c %s\n",s11.i1,s11.i2, s11.i3, s11.c, s11.str);
if(!s11.c)
printf("s11.c is null\n");
if(!*(s11.str))
printf("s11.str is null\n");
In gcc/vc++ sollte die Ausgabe sein:
0 2 0 1 0 0 0,000000 s11.c ist null s11.str ist null
Wissen Sie, wie Sie dem Compiler sagen können, dass er die Werte auf Null setzen soll?? Ich verwende GCC … gibt es einen Debug-Parameter, der dies tut?
– Busali
12. September 2009 um 4:24 Uhr
Verlassen Sie sich nicht auf den Compiler, um das Array zu initialisieren, verwenden Sie einen expliziten Initialisierer, wie Zan vorschlägt. Selbst wenn der aktuelle gcc Arrays in einem Debug-Modus auf Null setzt, kann der nächste entscheiden, sie mit einem völlig anderen Wert zu füllen, was Sie in 5 Jahren mit einem sehr schwer zu lokalisierenden Fehler zurücklässt. Geben Sie einfach die zusätzlichen 5 Zeichen ein und verwenden Sie das int-Array[10] = {0};
– Sonnenfinsternis
12. September 2009 um 4:43 Uhr
Offensichtlich falsch. Variablen aus dem Datensegment werden immer genullt.
Arrays initialisieren. Wenn wir ein reguläres Array mit lokalem Geltungsbereich (z. B. innerhalb einer Funktion) deklarieren und nichts anderes angeben, werden seine Elemente standardmäßig mit keinem Wert initialisiert, sodass ihr Inhalt unbestimmt ist, bis wir einen Wert in ihnen speichern. Die Elemente globaler und statischer Arrays werden dagegen automatisch mit ihren Defaultwerten initialisiert, was für alle fundamentalen Typen bedeutet, dass sie mit Nullen aufgefüllt werden.
In beiden Fällen, lokal und global, haben wir bei der Deklaration eines Arrays die Möglichkeit, jedem seiner Elemente Anfangswerte zuzuweisen, indem wir die Werte in geschweiften Klammern { } einschließen. Zum Beispiel:
int billy [5] = { 16, 2, 77, 40, 12071 };
14146800cookie-checkAnfangswert des int-Arrays in Cyes