Was ist der Unterschied zwischen einem Zeiger, der auf die Position 0x0 zeigt, und einem Zeiger, der auf NULL gesetzt ist?

12

Ist ein Zeiger, der auf 0x0000 zeigt, dasselbe wie ein Zeiger, der auf NULL gesetzt ist? Wenn der NULL-Wert in der C-Sprache definiert ist, an welchen Speicherort wird er dann physisch übersetzt? Ist es das gleiche wie 0x0000. Wo finde ich weitere Details zu diesen Konzepten?

Arpith
quelle
1
Dies wurde bereits auf Stack Overflow - stackoverflow.com/questions/1296843/… gefragt . Ich denke, es ist eine Grenze für uns, aber ich bin gewillt, es im Moment zweifelhaft zu machen.
ChrisF

Antworten:

12

Ein Punkt, den die meisten Antworten hier zumindest nicht explizit ansprechen, ist, dass ein Nullzeiger ein Wert ist, der während der Ausführung vorhanden ist, und eine Nullzeiger-Konstante ein syntaktisches Konstrukt ist, das im C-Quellcode vorhanden ist.

Eine Nullzeiger-Konstante ist , wie in der Antwort von Karlson richtig angegeben, entweder ein ganzzahliger konstanter Ausdruck mit dem Wert 0 (ein einfaches Beispiel 0ist das gebräuchlichste) oder ein solcher Ausdruck, der in void*(wie (void*)0) umgewandelt wird.

NULList ein Makro, das in <stddef.h>und mehreren anderen Standard-Headern definiert ist und zu einer implementierungsdefinierten Nullzeiger-Konstante erweitert wird . Die Erweiterung ist normalerweise entweder 0oder ((void*)0)(die äußeren Klammern werden benötigt, um andere Sprachregeln zu erfüllen).

0Wenn also ein Literal in einem Kontext verwendet wird, der einen Ausdruck vom Zeigertyp erfordert, wird es immer zu null pointereinem eindeutigen Zeigerwert ausgewertet, der auf kein Objekt verweist. Das macht nicht bedeuten , etwas über die Darstellung eines Null - Zeiger . Nullzeiger werden sehr häufig als All-Bit-Null dargestellt, können aber als alles dargestellt werden. Aber auch wenn ein Nullzeiger als dargestellt 0xDEADBEEFwird 0oder (void*)0immer noch eine Nullzeiger-Konstante ist .

Diese Antwort auf die Frage zum Stackoverflow deckt dies gut ab.

Dies impliziert unter anderem, dass memset()oder calloc(), das einen Speicherbereich auf Null setzen kann, keine Zeiger in diesem Bereich auf Null setzen muss. Bei den meisten Implementierungen ist dies wahrscheinlich der Fall, aber die Sprache garantiert dies nicht.

Ich weiß nicht , warum diese Frage nicht ein Duplikat betrachtet diese , oder wie es hier aktuell.

Keith Thompson
quelle
1
Eines meiner Probleme mit dem Design und der Entwicklung von C ist, dass die Ziffer Null weiterhin als nicht veraltete Darstellung eines Nullzeigers verwendet wird. In den frühesten Tagen der Sprache (zB vor dem Aufkommen von Dingen wie Funktionsprototypen) waren Zeiger und ganze Zahlen ausreichend austauschbar, so dass die Verwendung von "0" für einen Nullzeiger einfach war und "einfach funktioniert". Sobald es jedoch notwendig wurde, zwischen der ganzzahligen Menge Null und einem Nullzeiger zu unterscheiden, sollte die Darstellung "0" zugunsten eines Schlüsselworts oder einer Operatorfolge veraltet sein.
Supercat
Bedeutet dies, dass der NULL-Zeiger möglicherweise tatsächlich auf eine bestimmte Position verweist, wenn ihm plattformabhängig NULL zugewiesen wird? Die Nullzeiger-Konstante ist vielleicht ein syntaktisches Konstrukt, aber was passiert genau, wenn der Code ausgeführt wird? Nehmen wir an, dieses syntaktische Konstrukt wurde auf der GNU / Linux-Plattform kompiliert. Was ist der Zeigerwert, wenn wir ihm NULL zuweisen? Wie unterscheidet sich diese Adresse von jeder anderen Adresse?
Arpith
1
@Arpith: Durch Zuweisen NULLoder einer beliebigen Nullzeiger-Konstante zu einem Zeigerobjekt wird der Wert dieses Objekts auf einen Nullzeiger gesetzt . Auf der Maschinenebene kann es durchaus auf einen gültigen Speicherblock hindeuten. Das Dereferenzieren eines Nullzeigers hat ein undefiniertes Verhalten. Der Zugriff auf einen Teil des Speichers unter der Adresse 0x0000000ist ein gültiges Verhalten, genau wie alles andere. Diese Adresse unterscheidet sich von jeder anderen Adresse durch (a) Vergleichen gleich NULLund (b) Vergleichen ungleich einem Zeiger auf ein C-Objekt. Ein Nullzeiger ist ein beliebiger Zeigerwert, der angibt, dass er auf nichts verweist.
Keith Thompson
1
Auf der Maschine Ebene, es kann bis zu einem gewissen gültigen Teil des Speichers zeigen, aber in den meist C - Umgebungen wird es auf ungültige Speicher zeigen , so dass jeder Versuch , den Zeiger zu verwenden , in einer Hardware - Fall / Fehler / Ausnahme führen. Dies ist normalerweise nur auf den einfachsten Hardwareplattformen der Fall - Plattformen ohne Unterstützung für die Speicherverwaltung -, auf denen ein NULL-Zeiger auf einen gültigen Speicherort verweist.
Solomon Slow
7

Jede Plattform da draußen kann NULL frei definieren.

Wenn Sie einem Zeiger gemäß C-Standard Null zuweisen, wird er in einen NULL-Wert (für diese Plattform) konvertiert. Wenn Sie jedoch einen NULL-Zeiger verwenden und ihn in int umwandeln, gibt es keine Garantie dafür, dass Sie Null erhalten auf jeder Plattform da draußen. Tatsache ist jedoch, dass es auf den meisten Plattformen Null sein wird.

Informationen zu diesem Thema finden Sie in der C-Sprachspezifikation . Eine Quelle, für deren Vertrauenswürdigkeit ich nicht bürgen kann: http://www.winapi.co.kr/pds/doc/ISO-C-FDIS.1999-04.pdf

Mike Nakis
quelle
2
Wenn sie sich vom Standard lösen möchten, können sie ihn neu definieren NULL pointer constant. Soweit ich weiß, gibt es keine Compiler, die das tun.
Karlson
Gibt es einen Compiler, der NULL nicht als 0 implementiert? Und wird NULL garantiert als falsch bewertet?
Ugoren
NULL wird vom Standard garantiert als falsch bewertet. Ich weiß nicht, ob es einen Compiler (Plattform) gibt, der NULL nicht als 0 implementiert, und ich bezweifle es ernsthaft, aber der Standard verbietet es nicht, also wer weiß.
Mike Nakis
Es gibt eine Verwechslung zwischen der Darstellung der abstrakten "Nullzeiger-Konstante" (wie in der Spezifikation erwähnt) im Speicher, die dem Plattformhersteller gefällt, und der Definition des NULLMakros, das 0in C ++ und entweder 0oder (void *)0in C erweitert werden muss. denn das ist die echte "Nullzeiger-Konstante".
Jan Hudec
Während NULL theoretisch als alles definiert werden kann, gibt es jedoch eine Garantie durch den Standard, dass eine int-Konstante mit dem Wert 0, die in einen Zeiger geschrieben wird, zu einem Nullzeiger führt (ISO 9899: 1999 6.3.2.3/3). Das NULL-Makro von stddef.h muss ein Nullzeiger (7.17 / 3) sein, daher wäre es für den Compiler sehr mühsam, NULL nicht als 0 oder (void *) 0 zu implementieren.
1

Es ist in der Sprache C definiert, da es keine unveränderliche Maschinenadresse gibt, der es entspricht. Wenn es so wäre, bräuchten wir keine Abstraktion davon! Auch wenn auf den meisten Plattformen NULL möglicherweise irgendwann als 0 implementiert wird, ist es schlichtweg falsch anzunehmen, dass dies universell ist, wenn Sie sich überhaupt für Portabilität interessieren.

Kilian Foth
quelle
Das sind die Standards für open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
Karlson
0

Gemäß Abschnitt C Standarddokument6.3.2.3 :

Ein ganzzahliger konstanter Ausdruck mit dem Wert 0 oder ein solcher Ausdruck, der in den Typ void * umgewandelt wurde, wird als Nullzeigerkonstante bezeichnet.55) Wenn eine Nullzeigerkonstante in einen Zeigertyp konvertiert wird, lautet der resultierende Zeiger, der als Nullzeiger bezeichnet wird, garantiert nicht mit einem Zeiger auf ein Objekt oder eine Funktion zu vergleichen.

Bisher habe ich noch keinen Compiler gesehen, der sich davon gelöst hat.

Karlson
quelle
@ PéterTörök Du hast recht, es ist ein Typ. :)
Karlson
1
Ja, aber beachten Sie, dass es nichts über den Zeiger mit dem numerischen Wert 0 aussagt. Dies ist möglicherweise nicht der Fall, obwohl dies auf den meisten Plattformen der Fall ist.
Jan Hudec