Antwort

4

Nun, wie Sie wissen, ist die physische Darstellung von Nullzeiger eines bestimmten Typs nicht unbedingt Null-Bit-Muster. Wenn Sie einen Zeigerwert (beliebiger Zeiger) zwangsweise in einen Integer-Typ konvertieren, ist das Ergebnis eine Implementierung, aber normalerweise (und das ist die Absicht) bleibt der numerische Wert des Zeigers - die numerische Adresse - wenn möglich unverändert. Dies bedeutet, dass, wenn auf einer gegebenen Plattform ein Null-Zeiger vom Typ char * durch das Muster dargestellt wird (zum Beispiel), der obige Ausdruck zu 0xBAADF00D ausgewertet wird, und nicht zu Null. Dafür braucht man natürlich eine Plattform mit Null-Zeigern ungleich null. Ich habe persönlich nie mit solchen Plattformen gearbeitet, obwohl ich von einer Reihe von realen Plattformen wie der da draußen gehört habe (wie im Bereich der eingebetteten Plattformen ist es nicht ungewöhnlich).

Darüber hinaus als zusätzliche Note, Null-Pointer-Werte verschiedenen Typen können unterschiedliche physikalische Darstellungen haben, dass Sie unterschiedliche Werte in der Theorie Sinne von (size_t) ((int *) 0), (size_t) ((char *) 0) und (size_t) ((double *) 0) bekommen. Aber das wäre eine ziemlich exotische Situation, wenn auch aus der Sicht der abstrakten C-Sprache durchaus möglich.

P.S. Lesen Sie here (C FAQ) für einige Beispiele von tatsächlichen Plattformen mit Null-Null-Zeigern.

+0

Ich verstehe die theoretischen Argumente (die Sie gut erklären), aber ich bin auf der Suche nach Beispielen für tatsächliche Systeme, bei denen das Ausgeben eines Nullzeigers auf eine ganze Zahl in der Praxis zu einem Wert ungleich Null führt. –

+0

@Bruce Christensen: Siehe den Link zu C FAQ in P.S. – AnT

+0

Interessant. Sieht so aus, als ob einige alte Systeme Nicht-Null-Bit-Repräsentationen verwenden, aber es gibt keine modernen Beispiele in den FAQ. Es scheint ziemlich sicher zu sein, dass kein System, auf dem Linux ausgeführt wird, eine Darstellung ungleich Null verwendet oder dass die Implementierung von offsetof() unterbrochen wird (siehe http://google.com/codesearch/p?hl=de#huut-anHVuo/anonymous/kernel) /v2.6/linux-2.6.20.tar.bz2%7CqE0cR-WvTpY/linux-2.6.20/include/linux/stddef.h&q=stddef.h%20linux-2.6). –

1

Das einzige, was die C-Standard-Laufzeitdarstellung eines Null-Zeiger ist erforderlich ist (6.3.2.3/3 "Pointers"):

... der resultierende Zeiger, ein Null-Zeiger genannt, garantiert Vergleichen Sie ungleich mit einem Zeiger auf ein Objekt oder eine Funktion. Die Umwandlung eines Nullzeigers in einen anderen Zeigertyp ergibt einen Nullzeiger dieses Typs.

Alle zwei Nullzeiger müssen gleich sein.

Ihre Frage ist jedoch eine interessante Frage. Mir persönlich ist keine Plattform bekannt, die nicht den Laufzeitwert 0 verwendet, um einen Nullzeiger darzustellen. Der Standard erfordert dies jedoch nicht. Wenn Sie also die Annahme in Ihrem Code vermeiden können, warum nicht?

Ich würde auch an jedem interessiert sein, der ein System kennt, das einen Nicht-Null-Laufzeitwert für einen Nullzeiger verwendet.

0

Dies gilt nicht für char* oder sogar C, aber eine Smart-Pointer-Klasse, die Indizes in ein Array wählen könnten NULL als -1 darstellen, da 0 ein gültiger Array-Index ist.

Wenn man das Idiom memset(my_new_struct, 0, sizeof my_new_struct); betrachtet, ist es unwahrscheinlich, dass selbst ein Debugging-zentrisches System diese Identität bricht.

1

Der C99-Standard besagt, dass beim Konvertieren eines Ganzzahlwerts 0 in einen Zeiger ein NULL-Zeiger wird. Also ((char*)0) ist ein NULL-Zeiger. Ein NULL-Zeiger muss keine tatsächliche binäre Darstellung von 0 haben. Es kann zum Beispiel 0x12345678 sein.

Der C-Standard besagt weiterhin, dass wenn Sie einen NULL-Zeiger in eine Integer-Konstante konvertieren, das Ergebnis "implementierungsdefiniert" ist. In Wirklichkeit, was Compiler tun, ist einfach werfen Sie den numerischen Wert des Zeigers auf den entsprechenden ganzzahligen Wert, wie AndreyT sagte. Im obigen Beispiel könnte der Integer-Wert also 0x12345678 sein, obwohl es technisch gesehen alles sein könnte (dh der Compiler darf sagen: "einen NULL-Zeiger zurück in einen ganzzahligen Wert zu konvertieren ergibt den Wert 0xDEADBEEF"). Beachten Sie, dass dies bedeutet, dass der Compiler selbst bei Plattformen, auf denen der NULL-Zeiger den Wert 0 hat, diesen bei der Konvertierung in einen beliebigen ganzzahligen Wert konvertieren kann. In der Realität tun dies jedoch keine Compiler, weil es ziemlich verrückt wäre.

Also, ja, der C-Standard erlaubt eine Menge Dinge. In Wirklichkeit wird jede Plattform, an der Sie wahrscheinlich arbeiten, einen NULL-Zeiger als 0 darstellen und die Konvertierung eines NULL-Zeigers in einen ganzzahligen Wert ergibt 0. Suchen Sie here (section 1.14) für eine Liste einiger Ausnahmen von (obskuren) Architekturen, die 0 für einen Nullzeiger nicht verwenden.

Verwandte Themen