Der C-Standard garantiert, dass globale und statische Variablen immer vorhanden sind, wenn sie nicht initialisiert sind 0
.
Hier ist meine Frage: Die nicht initialisierten globalen und statischen Variablen gehen an BSS
Segment im Programm. Also die sog 0
sollte sein all-bit 0
.
Für ganzzahlige Variablen gilt: all-bit 0
wird gewertet als 0
. Die Fließkommavariablen, falls folgend IEEE754ist auch 0.0
. Aber für Zeiger müssen Nullzeiger nicht unbedingt sein all-bit 0
ebenso wie die Initialisierung eines globalen Zeigers wie folgt:
int* p = NULL;
machen keinen Unterschied zu nur:
int *p;
Der Standard garantiert, dass ein Zeiger mit statischer Speicherdauer und kein anderer Initialisierer als Nullzeiger initialisiert wird, unabhängig davon, um welches Bitmuster es sich handelt.
Die gleiche Grundidee gilt auch für Fließkomma- und Integer-Typen – sie werden garantiert auch mit 0 oder 0,0 initialisiert. Die Implementierung kann dies der Tatsache überlassen, dass BSS alle Bits genau dann auf 0 setzt, wenn es “weiß”, dass dies zu den richtigen Werten führt.
Alle Variablen mit statischer Speicherdauer werden garantiert auf ihre jeweiligen Nullwerte initialisiert, was im Allgemeinen nicht bedeutet, dass sie physikalisch mit einem Nur-Bit-Null-Muster gefüllt werden müssen.
Der Grund, warum solche Variablen auf einer bestimmten Plattform in das BSS-Segment gehen könnten, ist, dass der Nullzeiger auf der Zielplattform tatsächlich durch ein Nur-Bits-Null-Muster dargestellt wird. Das heißt, die All-Bits-Zero-Initialisierung für Zeiger funktioniert auf dieser Plattform einfach korrekt, sodass der Compiler BSS als einfachste und effizienteste Methode verwendet, um das richtige Verhalten auf dieser bestimmten Plattform zu implementieren. Wäre das nicht der Fall, müsste der Compiler solche statischen Variablen anders initialisieren.
Dies würde zum Beispiel für Gleitkommawerte gelten, wenn eine Plattform eine Nicht-IEEE 754-Darstellung für solche Werte mit einem Nicht-Null-Bitmuster zum Darstellen verwendet 0.0
(C schreibt IEEE 754 nicht vor).
(Außerdem galt dies früher sogar für alle ganzzahligen Typen größer als char
bis einer der TCs für den C99-Standard schließlich verlangte, dass das All-Bits-Zero-Muster eine gültige Objektdarstellung für ganzzahlige Nullen aller Typen auf allen C-Plattformen ist.)
Ein gutes Beispiel aus der Praxis kommt aus C++ (eine andere Sprache, aber in diesem Fall relevant). C++ gibt die gleiche Garantie für skalare Variablen mit statischer Speicherdauer. Mittlerweile verwenden viele gängige C++-Implementierungen 0xFFFFFFFF
value zur Darstellung von Nullzeigern vom Typ Zeiger auf Datenelement. Z.B
SomeType SomeClass::*p = 0;
tatsächlich in Code übersetzt, der füllt p
mit All-Bits-One-Muster. Wenn Sie also eine statische Variable dieses Typs ohne einen expliziten Initialisierer deklarieren, muss der Compiler sicherstellen, dass ihr Anfangswert ein Muster aus allen Bits und nicht aus Nullen ist. Es ist bekannt, dass einige Compiler Fehler machen, indem sie solche Variablen in BSS einfügen, sie vergessen und solche Variablen daher mit All-Bits-Null-Mustern gefüllt zurücklassen.
Hier einige gute Informationen: en.cppreference.com/w/cpp/language/zero_initialization
– Vaughn Cato
9. Juni 2013 um 18:19 Uhr
Dies ist kein Kommentar darüber, welchen Wert
p
hätte. Es ist eine Idee im Codierungsstil. Wenn Sie verwendenint *p
, wird die Notwendigkeit der Initialisierung auf NULL nicht betont. Es deutet darauf hin, dass der Anfangswert a ist egalauch wenn es initialisiert istNULL
durchC
.int* p = NULL;
impliziert das Programm braucht diese Initialisierung zu haben. Das ist der Unterschied, den ich sehe.– chux – Wiedereinsetzung von Monica
9. Juni 2013 um 18:31 Uhr