wake-up-neo.com

Was ist der Unterschied zwischen NULL, '\ 0' und 0?

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

Ich weiß, dass das ASCII Zeichen '0' Zu 48 Oder 0x30 Ausgewertet wird.

Der NULL Zeiger ist normalerweise wie folgt definiert:

#define NULL 0

Oder

#define NULL (void *)0

Darüber hinaus gibt es das Zeichen NUL'\0', Das anscheinend ebenfalls zu 0 Ausgewertet wird.

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

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

282
gnavi

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


Nullzeiger

Das ganzzahlige Konstantenliteral 0 Hat je nach Kontext, in dem es verwendet wird, unterschiedliche Bedeutungen. In allen Fällen handelt es sich immer noch um eine Ganzzahlkonstante mit dem Wert 0, Die nur auf verschiedene Arten beschrieben wird.

Wenn ein Zeiger mit dem Konstantenliteral 0 Verglichen wird, wird geprüft, ob der Zeiger ein Nullzeiger ist. Dieses 0 Wird dann als Nullzeiger-Konstante bezeichnet. Der C-Standard definiert, dass 0, Das in den Typ void * Umgewandelt wird, sowohl ein Nullzeiger als auch eine Nullzeiger-Konstante ist.

Zur besseren Lesbarkeit ist das Makro NULL in der Header-Datei stddef.h Enthalten. Abhängig von Ihrem Compiler kann es möglich sein, #undef NULL Und es zu etwas Verrücktem zu definieren.

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

if (pointer == NULL)

NULL ist definiert, um einen Vergleich mit einem Nullzeiger durchzuführen. Es ist implementierungsdefiniert, wie die tatsächliche Definition von NULL lautet, solange es sich um eine gültige Nullzeiger-Konstante handelt.

if (pointer == 0)

0 Ist eine weitere Darstellung der Nullzeiger-Konstante.

if (!pointer)

Diese if -Anweisung prüft implizit, ob "nicht 0" ist, und kehrt dies um, um zu bedeuten, dass "0" ist.

Die folgenden Methoden 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 für zwei Variablen. Dies might funktioniert, wenn sich mynull nie im Code ändert und die Compiler-Optimierungskonstante die 0 in die if-Anweisung faltet, dies jedoch nicht garantiert ist und der Compiler mindestens eine Diagnosemeldung (Warnung) ausgeben muss oder Fehler) nach dem C-Standard.

Beachten Sie, dass in der Sprache C ein Nullzeiger vorliegt. Auf die zugrunde liegende Architektur kommt es nicht an. Wenn die zugrunde liegende Architektur einen Nullzeigerwert hat, der als Adresse 0xDEADBEEF definiert ist, muss der Compiler dieses Durcheinander sortieren.

Selbst in dieser witzigen Architektur sind die folgenden Methoden immer noch gültig, um nach einem Nullzeiger zu suchen:

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

Die folgenden Methoden 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. Dies hat nichts mit Zeigern zu tun. Möglicherweise sehen Sie jedoch etwas Ähnliches wie diesen Code:

if (!*string_pointer)

prüft, ob der Zeichenkettenzeiger auf ein Nullzeichen zeigt

if (*string_pointer)

prüft, ob der Zeichenkettenzeiger auf ein Nicht-Null-Zeichen zeigt

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

Außerdem ist '\0' (Wie alle Zeichenliterale) eine Ganzzahlkonstante, in diesem Fall mit dem Wert Null. '\0' Ist also völlig gleichbedeutend mit einer schmucklosen 0 - Ganzzahlkonstante - der einzige Unterschied besteht in der Absicht, die es einem menschlichen Leser vermittelt ("Ich bin Verwenden Sie dies als Nullzeichen. ").

Verweise

Siehe Frage 5.3 der FAQ zu comp.lang.c für weitere Informationen. Siehe dieses pdf für den C-Standard. Lesen Sie die Abschnitte 6.3.2.3, Hinweise, Absatz 3.

327
Andrew Keeton

Es scheint, dass einige Leute die Unterschiede zwischen NULL, '\ 0' und 0 falsch verstehen. Also, um zu erklären und um zu vermeiden, Dinge zu wiederholen, die zuvor gesagt wurden:

Ein konstanter Ausdruck vom Typ int mit dem Wert 0 oder ein Ausdruck dieses Typs, der in den Typ void * umgewandelt wird, ist eine Nullzeiger-Konstante, die bei Umwandlung in einen Zeiger zu einem Nullzeiger) wird. Der Standard garantiert den Vergleich ngleich einem Zeiger auf ein Objekt oder eine Funktion.

NULL ist ein Makro, definiert als Nullzeiger-Konstante.

'\ 0' ist eine Konstruktion, die für das Nullzeichen zum Beenden einer Zeichenfolge verwendet wird.

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

33
amaterasu

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 Byte, die anderen 8 Byte Nullen).
  • string-Kontext - Das Zeichen, das die Ziffer Null darstellt, hat einen Hex-Wert von 0x30, während das NUL-Zeichen einen Hex-Wert von 0x00 hat (wird zum Beenden von Strings verwendet).

Diese drei sind immer unterschiedlich, 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 klärt es.

14
Nasko

Wenn NULL und 0 als Nullzeiger-Konstanten äquivalent sind, welche sollte ich verwenden? in der C FAQ Liste behandelt auch dieses Problem:

C-Programmierer müssen verstehen, dass NULL und 0 In Zeigerkontexten austauschbar sind und dass ein uncast 0 Durchaus akzeptabel ist. Jede Verwendung von NULL (im Gegensatz zu 0) Sollte als sanfte Erinnerung betrachtet werden, dass ein Zeiger beteiligt ist. Programmierer sollten nicht darauf angewiesen sein (weder für ihr eigenes Verständnis noch für das des Compilers), um Zeiger 0 von Integer 0 zu unterscheiden.

Nur in Zeigerkontexten sind NULL und 0 Äquivalent. NULL sollte nicht verwendet werden, wenn eine andere Art von 0 erforderlich ist, obwohl dies möglicherweise funktioniert, da dadurch die falsche stilistische Nachricht gesendet wird. (Außerdem erlaubt ANSI, dass die Definition von NULL((void *)0) Ist, was in Nicht-Zeigerkontexten überhaupt nicht funktioniert.) Verwenden Sie NULL insbesondere nicht, wenn ASCII Nullzeichen (NUL) ist erwünscht. Geben Sie Ihre eigene Definition an

#define NUL '\0'

wenn du musst.

6
Sinan Ünür

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

"Nullzeichen (NUL)" ist am einfachsten auszuschließen. '\0' Ist ein Zeichenliteral. In C wird es als int implementiert, also ist es dasselbe wie 0, was INT_TYPE_SIZE Entspricht. In C++ wird das Zeichenliteral als char implementiert, was 1 Byte entspricht. Dies unterscheidet sich normalerweise von NULL oder 0.

Als nächstes ist NULL ein Zeigerwert, der angibt, dass eine Variable auf keinen Adressraum verweist. Abgesehen von der Tatsache, dass es normalerweise als Null implementiert ist, muss es in der Lage sein, den gesamten Adressraum der Architektur auszudrücken. Auf einer 32-Bit-Architektur ist NULL (wahrscheinlich) 4 Byte und auf einer 64-Bit-Architektur 8 Byte. Dies liegt an der Umsetzung von C.

Schließlich hat das Literal 0 Den Typ int, der die Größe INT_TYPE_SIZE Hat. Der Standardwert von INT_TYPE_SIZE Kann je nach Architektur unterschiedlich sein.

Apple schrieb:

Das von Mac OS X verwendete 64-Bit-Datenmodell wird als "LP64" bezeichnet. Dies ist das übliche Datenmodell, das von anderen 64-Bit-UNIX-Systemen von Sun und SGI sowie von 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 : Das Zeichenliteral wurde erweitert.

#include <stdio.h>

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

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

5
Eugene Yokota

Ein 1-L-NUL beendet eine Zeichenfolge.

Ein NULL-Wert von zwei L weist auf nichts hin.

Und ich werde einen goldenen Stier wetten

Dass es keine Drei-L-NULL gibt.

Wie gehen Sie mit NUL um?

4
EvilTeach

Ein gutes Stück, das mir beim Einstieg in C hilft (Aus der Expert C-Programmierung von Linden)

Das Eine 'l' nul und die Zwei 'l' null

Merken Sie sich diesen kleinen Reim, um die korrekte Terminologie für Zeiger und ASCII null:

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 Zeichen ASCII mit dem Bitmuster Null wird als "NUL" bezeichnet. Der spezielle Zeigerwert, der bedeutet, dass der Zeiger nirgendwo steht, ist "NULL". Die beiden Begriffe sind in ihrer Bedeutung nicht austauschbar.

4
dlmeetei

"NUL" ist nicht 0, sondern bezieht sich auf das Zeichen ASCII NUL. Zumindest habe ich das so gesehen. Der Nullzeiger wird oft als 0 definiert, dies hängt jedoch vom Wert ab Umgebung, in der Sie ausgeführt werden, und die Angabe des Betriebssystems oder der Sprache, die Sie verwenden.

In ANSI C wird der Nullzeiger als ganzzahliger Wert 0 angegeben. Daher ist jede Welt, in der dies nicht zutrifft, nicht ANSI C-kompatibel.

2
peterb

Es wird nicht garantiert, dass NULL 0 ist - sein genauer Wert ist architekturabhängig. Die meisten großen Architekturen definieren es zu (void*)0.

'\0' ist immer gleich 0, weil so Byte 0 in einem Zeichenliteral codiert wird.

Ich erinnere mich nicht, ob C-Compiler erforderlich sind, um ASCII - wenn nicht, '0' ist möglicherweise nicht immer gleich 48. Unabhängig davon ist es unwahrscheinlich, dass Sie jemals auf ein System stoßen, das einen alternativen Zeichensatz wie EBCDIC verwendet, es sei denn, Sie arbeiten an sehr obskuren Systemen.

Die Größen der verschiedenen Typen unterscheiden sich auf 64-Bit-Systemen, aber die ganzzahligen Werte sind gleich.


Einige Kommentatoren haben Zweifel geäußert, dass NULL gleich 0 ist, aber nicht sei Null. Hier ist ein Beispielprogramm zusammen mit der erwarteten Ausgabe auf einem solchen System:

#include <stdio.h>

int main () {
    size_t ii;
    int *ptr = NULL;
    unsigned long *null_value = (unsigned long *)&ptr;
    if (NULL == 0) {
        printf ("NULL == 0\n"); }
    printf ("NULL = 0x");
    for (ii = 0; ii < sizeof (ptr); ii++) {
        printf ("%02X", null_value[ii]); }
    printf ("\n");
    return 0;
}

Dieses Programm könnte drucken:

NULL == 0
NULL = 0x00000001
0
John Millikin

Ein Byte mit dem Wert 0x00 ist in der Tabelle ASCII) das Sonderzeichen "NUL" oder "NULL". In C sollten Sie Steuerzeichen nicht in Ihren Quellcode einbetten Dies wird in C-Strings mit einer maskierten 0 dargestellt, dh "\ 0".

Aber ein wahrer NULL-Wert ist nicht ein Wert. Es ist das Fehlen eines Wertes. Für einen Zeiger bedeutet dies, dass der Zeiger nichts zu zeigen hat. In einer Datenbank bedeutet dies, dass ein Feld keinen Wert enthält (was nicht dasselbe ist, als wenn das Feld leer, 0 oder mit Leerzeichen gefüllt ist).

Der tatsächliche Wert, den ein bestimmtes System- oder Datenbankdateiformat zur Darstellung eines NULL-Werts verwendet, muss nicht unbedingt 0x00 sein.

0
richardtallent