Was ist der Unterschied zwischen NULL, ‘\0’ und 0?

Lesezeit: 11 Minuten

Benutzeravatar von gnavi
gnavi

In C scheint es Unterschiede zwischen verschiedenen Werten von Null zu geben — NULL, NUL und 0.

Ich kenne das ASCII-Zeichen '0' wertet zu 48 oder 0x30.

Das NULL Zeiger wird normalerweise definiert als:

#define NULL 0

Oder

#define NULL (void *)0

Außerdem gibt es die NUL Charakter '\0' das scheint zu bewerten 0 auch.

Gibt es Zeiten, in denen diese drei Werte nicht gleich sein können?

Gilt das auch für 64-Bit-Systeme?

  • Weitere Informationen zu den Unterschieden zwischen 0 und NULL finden Sie unter stackoverflow.com/questions/176989/….

    – David Rodríguez – Dribeas

    19. August 2009 um 7:22 Uhr

  • Die Kennung NUL existiert nicht in der C-Standardsprache oder -Bibliothek (oder in C++, soweit ich weiß). Das Nullzeichen wird manchmal NUL genannt, aber es wird normalerweise nur als C oder C++ bezeichnet '\0'.

    – Keith Thompson

    9. Juli 2013 um 2:09 Uhr

Notiz: Diese Antwort gilt für die Sprache C, nicht für C++.


Nullzeiger

Das ganzzahlige Konstantenliteral 0 hat je nach Kontext, in dem es verwendet wird, unterschiedliche Bedeutungen. In allen Fällen ist es immer noch eine ganzzahlige Konstante mit dem Wert 0es wird nur unterschiedlich beschrieben.

Wenn ein Zeiger mit dem konstanten Literal verglichen wird 0, dann ist dies eine Überprüfung, ob der Zeiger ein Nullzeiger ist. Dies 0 wird dann als Nullzeigerkonstante bezeichnet. Der C-Standard definiert das 0 auf den Typ werfen void * ist sowohl ein Nullzeiger als auch eine Nullzeigerkonstante.

Um die Lesbarkeit zu verbessern, enthält das Makro zusätzlich NULL wird in der Header-Datei bereitgestellt stddef.h. Abhängig von Ihrem Compiler ist dies möglicherweise möglich #undef NULL und definiere es zu etwas Verrücktem neu.

Daher sind hier einige gültige Möglichkeiten, um nach einem Nullzeiger zu suchen:

if (pointer == NULL)

NULL ist so definiert, dass es mit einem Nullzeiger gleich verglichen wird. Es wird die Implementierung definiert, was die eigentliche Definition von ist NULL ist, solange es sich um eine gültige Nullzeigerkonstante handelt.

if (pointer == 0)

0 ist eine weitere Darstellung der Nullzeigerkonstante.

if (!pointer)

Dies if -Anweisung überprüft implizit “ist nicht 0”, also kehren wir das um und bedeuten “ist 0”.

Die folgenden Möglichkeiten sind UNGÜLTIG, um nach einem Nullzeiger zu suchen:

int mynull = 0;
<some code>
if (pointer == mynull)

Für den Compiler ist dies keine Prüfung auf einen Nullzeiger, sondern eine Gleichheitsprüfung zweier Variablen. Dies könnte funktionieren, wenn sich mynull nie im Code ändert und die Compiler-Optimierungskonstante die 0 in die if-Anweisung faltet, aber dies ist nicht garantiert und der Compiler muss gemäß dem C-Standard mindestens eine Diagnosemeldung (Warnung oder Fehler) erzeugen.

Beachten Sie, dass der Wert eines Nullzeigers in der Sprache C für die zugrunde liegende Architektur keine Rolle spielt. Wenn die zugrunde liegende Architektur einen Nullzeigerwert hat, der als Adresse 0xDEADBEEF definiert ist, ist es Sache des Compilers, dieses Durcheinander zu beseitigen.

Daher sind selbst bei dieser lustigen Architektur die folgenden Methoden immer noch gültig, um nach einem Nullzeiger zu suchen:

if (!pointer)
if (pointer == NULL)
if (pointer == 0)

Die folgenden Möglichkeiten sind UNGÜLTIG, um nach einem Nullzeiger zu suchen:

#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)

da diese von einem Compiler als normale Vergleiche angesehen werden.

Nullzeichen

'\0' ist als Nullzeichen definiert – das ist ein Zeichen, bei dem alle Bits auf Null gesetzt sind. '\0' ist (wie alle Zeichenliterale) eine ganzzahlige Konstante, in diesem Fall mit dem Wert Null. So '\0' ist völlig gleichbedeutend mit einem schmucklosen 0 ganzzahlige Konstante – der einzige Unterschied liegt in der Absicht die es einem menschlichen Leser vermittelt (“Ich verwende dies als Nullzeichen.”).

'\0' hat nichts mit Zeigern zu tun. Möglicherweise sehen Sie jedoch etwas Ähnliches wie diesen Code:

if (!*char_pointer)

prüft, ob der char-Zeiger auf ein Nullzeichen zeigt.

if (*char_pointer)

prüft, ob der char-Zeiger auf ein Nicht-Null-Zeichen zeigt.

Verwechseln Sie diese nicht mit Nullzeigern. Nur weil die Bit-Darstellung dieselbe ist und dies einige bequeme Crossover-Fälle ermöglicht, sind sie nicht wirklich dasselbe.

Verweise

Sehen Frage 5.3 der comp.lang.c-FAQ für mehr. Sehen dieses pdf für den C-Standard. Siehe Abschnitte 6.3.2.3 Hinweise, Absatz 3.

  • Danke für den Hinweis auf die FAQ-Liste. Siehe aber auch c-faq.com/null/nullor0.html

    – Sinan Ünür

    18. August 2009 um 22:35 Uhr

  • Nein, Sie werden nicht vergleichen ptr zu alle bits-null. Das ist kein memcmp, aber dies ist ein Vergleich mit einem eingebauten Operator. Die eine Seite ist eine Nullzeigerkonstante '\0', und die andere Seite ist ein Zeiger. Sowie bei den anderen beiden Versionen mit NULL und 0. Diese drei tun dasselbe.

    – Johannes Schaub – litb

    18. August 2009 um 22:46 Uhr

  • Sie nehmen den eingebauten Vergleichsoperator als etwas, das Bit-Strings vergleichen würde. Aber das ist es nicht. Es vergleicht zwei Werte, die abstrakte Konzepte sind. Also ein Nullzeiger, der intern dargestellt wird als 0xDEADBEEF ist immer noch ein Nullzeiger, egal wie sein Bitstring aussieht, und er wird immer noch gleich vergleichen NULL, 0, \0 und alle anderen Nullzeiger-Konstantenformen.

    – Johannes Schaub – litb

    18. August 2009 um 22:48 Uhr

  • Sie machen einen guten Punkt über den Vergleichsoperator. Ich habe C99 aufgefrischt. Es heißt: “Ein ganzzahliger konstanter Ausdruck mit dem Wert 0 oder ein solcher Ausdruck, der in den Typ void * umgewandelt wird, wird als Nullzeigerkonstante bezeichnet.” Es besagt auch, dass ein Zeichenliteral ein ganzzahliger konstanter Ausdruck ist. Durch die transitive Eigenschaft haben Sie damit Recht ptr == '\0'.

    – Andreas Keeton

    18. August 2009 um 22:56 Uhr

  • “….es könnte möglich sein, #undef NULL zu etwas Verrücktem umzudefinieren. Jeder, der so etwas tut, verdient es, erschossen zu werden.” Das, mein guter Herr, hat mich zum Lachen gebracht …

    – oggiemc

    1. April 2014 um 16:56 Uhr

Benutzeravatar von amaterasu
amaterasu

Es scheint, dass einige Leute die Unterschiede zwischen NULL, ‘\0’ und 0 missverstehen. Also, um es zu erklären und um zu vermeiden, Dinge zu wiederholen, die zuvor gesagt wurden:

Ein konstanter Ausdruck des Typs int mit dem Wert 0 oder ein Ausdruck dieses Typs in einen Typ umgewandelt void * ist ein Nullzeiger konstantdie bei Umwandlung in einen Zeiger zu a wird Null Zeiger. Der Vergleich ist durch die Norm gewährleistet ungleich einem Zeiger auf ein Objekt oder eine Funktion.

NULL ist ein Makro, definiert in als a Nullzeiger konstant.

\0 ist eine Konstruktion, die verwendet wird, um die darzustellen Nullzeichenwird verwendet, um eine Zeichenfolge abzuschließen.

EIN Nullzeichen ist ein Byte, dessen Bits alle auf 0 gesetzt sind.

  • Du hast verpasst 0.

    – Schrittmacher

    19. Juli 2021 um 10:06 Uhr


  • “definiert in als”?

    – Endolith

    25. Mai um 15:30 Uhr

Benutzeravatar von Nasko
Nasko

Alle drei definieren die Bedeutung von Null in unterschiedlichen Zusammenhängen.

  • Zeigerkontext – NULL wird verwendet und bedeutet, dass der Wert des Zeigers 0 ist, unabhängig davon, ob es sich um 32-Bit- oder 64-Bit handelt (ein Fall 4 Bytes, die anderen 8 Bytes Nullen).
  • String-Kontext – das Zeichen, das die Ziffer Null darstellt, hat einen Hexadezimalwert von 0x30, während das NUL-Zeichen einen Hexadezimalwert von 0x00 hat (wird zum Beenden von Zeichenketten verwendet).

Diese drei sind immer anders, wenn man sich die Erinnerung ansieht:

NULL - 0x00000000 or 0x00000000'00000000 (32 vs 64 bit)
NUL - 0x00 or 0x0000 (ascii vs 2byte unicode)
'0' - 0x20

Ich hoffe, das verdeutlicht es.

  • Nasko: Bewerten sizeof('\0') und lass dich überraschen.

    – Café

    19. August 2009 um 0:58 Uhr

  • @Nasko: Ich war wirklich überrascht: mit gcc in C: sizeof(‘\0’) == sizeof(‘a’) == 4, während mit g++ in C++: sizeof(‘\0’) == sizeof (‘a’) == 1

    – David Rodríguez – Dribeas

    19. August 2009 um 7:51 Uhr

  • @Nasko: Aus dem C-Standard (Entwurf, n1124): ‘Eine ganzzahlige Zeichenkonstante hat den Typ int’, daher ist ‘\0’ in C tatsächlich vom Typ int, und daher ist sizeof(‘\0’) in meiner Architektur 4 (Linux, 32bit)

    – David Rodríguez – Dribeas

    19. August 2009 um 8:02 Uhr

  • @dribeas – Ich habe es nicht als Konstante beschrieben, sondern als Teil der Zeichenfolge. Ich hätte es definitiv explizit machen können. Vielen Dank

    – Nasso

    19. August 2009 um 15:27 Uhr

  • @DavidRodríguez-dribeas Bearbeitung rückgängig machen “ASCII-Wert ‘0’ auf 0x20 (32. Dez.) korrigiert”

    – chux – Wiedereinsetzung von Monica

    22. September 2017 um 19:28 Uhr

Wenn NULL und 0 als Nullzeigerkonstanten gleichwertig sind, welche sollte ich verwenden? in der C-FAQ-Liste behandelt dieses Problem ebenfalls:

C-Programmierer müssen das verstehen
NULL und 0 in Zeigerkontexten austauschbar sind, und dass ein Uncast 0
ist vollkommen akzeptabel. Jede Verwendung von NULL (im Gegensatz zu 0) sollte als sanfte Erinnerung angesehen werden, dass es sich um einen Zeiger handelt; Programmierer sollten sich nicht darauf verlassen (weder für ihr eigenes Verständnis noch für das des Compilers), um Zeiger zu unterscheiden
0‘s von Integer 0‘s.

Das ist nur in Zeigerkontexten der Fall
NULL und 0 sind gleichwertig. NULL sollte nicht verwendet werden, wenn eine andere Art von 0 ist erforderlich, obwohl es funktionieren könnte, da dies die falsche stilistische Botschaft sendet. (Außerdem erlaubt ANSI die Definition von NULL sein
((void *)0)was in Nicht-Zeiger-Kontexten überhaupt nicht funktioniert.) Verwenden Sie insbesondere nicht NULL wenn das ASCII-Nullzeichen (NUL) ist erwünscht. Geben Sie Ihre eigene Definition an

#define NUL '\0'

wenn du musst.

Benutzeravatar von Eugene Yokota
Eugen Yokota

Was ist der Unterschied zwischen NULL, ‘\0’ und 0

“Nullzeichen (NUL)” ist am einfachsten auszuschließen. '\0' ist ein Zeichenliteral. In C ist es implementiert als intalso ist es dasselbe wie 0, was von ist INT_TYPE_SIZE. In C++ ist das Zeichenliteral implementiert als char, das ist 1 Byte. Dies unterscheidet sich normalerweise von NULL oder 0.

Nächste, NULL ist ein Zeigerwert, der angibt, dass eine Variable auf keinen Adressraum zeigt. Abgesehen von der Tatsache, dass es normalerweise als Nullen implementiert wird, muss es in der Lage sein, den gesamten Adressraum der Architektur auszudrücken. Daher ist NULL auf einer 32-Bit-Architektur (wahrscheinlich) 4 Byte und auf einer 64-Bit-Architektur 8 Byte. Dies liegt an der Implementierung von C.

Endlich das wörtliche 0 ist vom Typ intdie von der Größe ist INT_TYPE_SIZE. Der Standardwert von INT_TYPE_SIZE kann je nach Architektur unterschiedlich sein.

Apfel schrieb:

Das von Mac OS X verwendete 64-Bit-Datenmodell ist als “LP64” bekannt. Dies ist das gemeinsame Datenmodell, das von anderen 64-Bit-UNIX-Systemen von Sun und SGI sowie 64-Bit-Linux verwendet wird. Das LP64-Datenmodell definiert die primitiven Typen wie folgt:

  • ints sind 32-Bit
  • Longs sind 64-Bit
  • Long-Longs sind auch 64-Bit
  • Zeiger sind 64-Bit

Wikipedia 64-Bit:

Der VC++-Compiler von Microsoft verwendet das LLP64-Modell.

64-bit data models
Data model short int long  long long pointers Sample operating systems
LLP64      16    32  32    64        64       Microsoft Win64 (X64/IA64)
LP64       16    32  64    64        64       Most Unix and Unix-like systems (Solaris, Linux, etc.)
ILP64      16    64  64    64        64       HAL
SILP64     64    64  64    64        64       ?

Bearbeiten: Mehr zum Zeichenliteral hinzugefügt.

#include <stdio.h>

int main(void) {
    printf("%d", sizeof('\0'));
    return 0;
}

Der obige Code gibt 4 auf gcc und 1 auf g++ zurück.

  • Nein, '\0' ist nicht ein 1-Byte-Wert. Es ist ein Zeichenliteral, das ein ganzzahliger konstanter Ausdruck ist – wenn also gesagt werden kann, dass es eine Größe hat, dann ist es die Größe von an int (der mindestens 2 Byte groß sein muss). Wenn Sie mir nicht glauben, bewerten Sie sizeof('\0') und sehen Sie selbst. '\0', 0 und 0x0 sind alle völlig gleichwertig.

    – Café

    19. August 2009 um 1:06 Uhr

  • @caf es kommt auf die Sprache an. Wenn Sie mir nicht glauben, versuchen Sie es sizeof('\0') auf einem C++-Compiler.

    – Eugen Yokota

    19. August 2009 um 14:30 Uhr

  • Sie sollten “%zu” verwenden, wenn Sie sizeof(something) drucken

    – Ungebraucht

    26. Februar 2015 um 8:46 Uhr


  • In C ist es 4 auf Ihrem Computer, nur wegen der automatischen Umwandlung, die standardmäßig int ist. Weisen Sie diesen Wert ohne Umformung einem char, einem int oder einem long long int zu und seine Größe ändert sich entsprechend. Auch die Größe von ‘a’ ist 4 aus einer Variablen.

    Benutzer17492848

    25. Dezember 2021 um 0:22 Uhr


Benutzeravatar von Intrastellar Explorer
Intrastellarer Entdecker

Ein gutes Stück, das mir beim Einstieg in C hilft (aus dem Expert C Programming von Linden)

Das Eins ‘l’ null und das Zwei ‘l’ null

Merken Sie sich diesen kleinen Reim, um sich an die korrekte Terminologie für Zeiger und ASCII-Null zu erinnern:

The one "l" NUL ends an ASCII string,

The two "l" NULL points to no thing.

Apologies to Ogden Nash, but the three "l" nulll means check your spelling. 
  • Das ASCII-Zeichen mit dem Bitmuster Null wird als “NUL” bezeichnet.
  • Der spezielle Zeigerwert, der bedeutet, dass der Zeiger nirgendwohin zeigt, ist “NULL”.
  • Die beiden Begriffe sind in ihrer Bedeutung nicht austauschbar.

  • Nein, '\0' ist nicht ein 1-Byte-Wert. Es ist ein Zeichenliteral, das ein ganzzahliger konstanter Ausdruck ist – wenn also gesagt werden kann, dass es eine Größe hat, dann ist es die Größe von an int (der mindestens 2 Byte groß sein muss). Wenn Sie mir nicht glauben, bewerten Sie sizeof('\0') und sehen Sie selbst. '\0', 0 und 0x0 sind alle völlig gleichwertig.

    – Café

    19. August 2009 um 1:06 Uhr

  • @caf es kommt auf die Sprache an. Wenn Sie mir nicht glauben, versuchen Sie es sizeof('\0') auf einem C++-Compiler.

    – Eugen Yokota

    19. August 2009 um 14:30 Uhr

  • Sie sollten “%zu” verwenden, wenn Sie sizeof(something) drucken

    – Ungebraucht

    26. Februar 2015 um 8:46 Uhr


  • In C ist es 4 auf Ihrem Computer, nur wegen der automatischen Umwandlung, die standardmäßig int ist. Weisen Sie diesen Wert ohne Umformung einem char, einem int oder einem long long int zu und seine Größe ändert sich entsprechend. Auch die Größe von ‘a’ ist 4 aus einer Variablen.

    Benutzer17492848

    25. Dezember 2021 um 0:22 Uhr


Benutzeravatar der Community
Gemeinschaft

Ein Eins-L NUL beendet eine Zeichenfolge.

Ein zwei-L NULL zeigt auf nichts.

Und ich werde einen goldenen Bullen wetten

Dass es kein Drei-L-NULLL gibt.

Wie gehen Sie mit NULL um?

1427500cookie-checkWas ist der Unterschied zwischen NULL, ‘\0’ und 0?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy