391 Stimmen

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

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

Ich weiß, dass das ASCII-Zeichen '0' wertet aus zu 48 o 0x30 .

Die NULL Zeiger ist in der Regel definiert als:

#define NULL 0

Ou

#define NULL (void *)0

Darüber hinaus gibt es die NUL Zeichen '\0' was anscheinend zu folgenden Ergebnissen führt 0 auch.

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

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

436voto

Andrew Keeton Punkte 20477

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


Null-Zeiger

Die ganzzahlige Konstante literal 0 hat je nach dem Kontext, in dem es verwendet wird, unterschiedliche Bedeutungen. In allen Fällen handelt es sich um eine Integer-Konstante mit dem Wert 0 Sie wird nur auf unterschiedliche Weise beschrieben.

Wenn ein Zeiger mit dem konstanten Literal verglichen wird 0 ist dies eine Prüfung, ob der Zeiger ein Null-Zeiger ist. Diese 0 wird dann als Null-Zeiger-Konstante bezeichnet. Der C-Standard definiert, dass 0 in den Typ gegossen void * ist sowohl ein Null-Zeiger als auch eine Null-Zeiger-Konstante.

Um die Lesbarkeit zu verbessern, wurde außerdem das Makro NULL ist in der Header-Datei enthalten stddef.h . Abhängig von Ihrem Compiler kann es möglich sein #undef NULL und sie in etwas Verrücktes umdefinieren.

Daher sind hier einige gültige Möglichkeiten, um auf einen Null-Zeiger zu prüfen:

if (pointer == NULL)

NULL ist so definiert, dass er mit einem Null-Zeiger gleichzusetzen ist. Es ist durch die Implementierung definiert, was die tatsächliche Definition von NULL ist, sofern es sich um eine gültige Null-Zeiger-Konstante handelt.

if (pointer == 0)

0 ist eine weitere Darstellung der Null-Zeiger-Konstante.

if (!pointer)

Diese if Anweisung prüft implizit "ist nicht 0", also kehren wir das um und meinen "ist 0".

Die folgenden Methoden zur Prüfung auf einen Null-Zeiger sind unzulässig:

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

Für den Compiler ist dies keine Prüfung auf einen Null-Zeiger, sondern eine Gleichheitsprüfung für zwei Variablen. Diese könnte funktionieren, wenn sich mynull im Code nie ändert und die Compiler-Optimierungen die 0 konstant in die if-Anweisung falten, aber das ist nicht garantiert, und der Compiler muss gemäß dem C-Standard mindestens eine Diagnosemeldung (Warnung oder Fehler) erzeugen.

Beachten Sie, dass der Wert eines Null-Zeigers in der Sprache C auf der zugrunde liegenden Architektur keine Rolle spielt. Wenn die zugrunde liegende Architektur einen Null-Zeiger-Wert hat, der als Adresse 0xDEADBEEF definiert ist, muss der Compiler dieses Durcheinander in Ordnung bringen.

Daher sind selbst auf dieser lustigen Architektur die folgenden Möglichkeiten immer noch gültig, um auf einen Nullzeiger zu prüfen:

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

Die folgenden Methoden zur Prüfung auf einen Null-Zeiger sind unzulässig:

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

da diese von einem Compiler als normale Vergleiche angesehen werden.

Null-Zeichen

'\0' ist als Nullzeichen definiert, d. h. als ein Zeichen, bei dem alle Bits auf Null gesetzt sind. '\0' ist (wie alle Zeichenliterale) eine Integer-Konstante, in diesem Fall mit dem Wert Null. Also '\0' ist völlig gleichwertig mit einem unverzierten 0 Integer-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. Sie können jedoch etwas ähnliches wie diesen Code sehen:

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.

Diese sind nicht mit Nullzeigern zu verwechseln. Nur weil die Bit-Darstellung ist die gleiche, und dies ermöglicht für einige bequeme Cross-over-Fälle, sie sind nicht wirklich die gleiche Sache.

Referenzen

Siehe Frage 5.3 der comp.lang.c FAQ für mehr. Siehe dieses pdf für den C-Standard. Sehen Sie sich Abschnitt 6.3.2.3 Zeiger, Absatz 3 an.

45voto

amaterasu Punkte 1000

Es scheint, dass einige Leute die Unterschiede zwischen NULL, ' \0 ' und 0 sind. Also, um das zu erklären und um zu vermeiden, dass ich Dinge wiederhole, die ich bereits gesagt habe:

Ein konstanter Ausdruck des Typs int mit dem Wert 0, oder ein Ausdruck dieses Typs, der in den Typ void * ist eine Null-Zeiger-Konstante der, wenn er in einen Zeiger umgewandelt wird, zu einem Null-Zeiger . Der Standard garantiert den Vergleich ungleich einem Zeiger auf ein beliebiges Objekt oder eine Funktion .

NULL ist ein Makro, definiert als ein Null-Zeiger-Konstante .

\0 ist eine Konstruktion, die zur Darstellung der Nullzeichen verwendet, um eine Zeichenkette zu beenden.

A Nullzeichen ist ein Byte, bei dem alle Bits auf 0 gesetzt sind.

18voto

Nasko Punkte 1232

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 einen 32-Bit- oder 64-Bit-Zeiger handelt (in einem Fall 4 Bytes, im anderen 8 Bytes mit Nullen).
  • String-Kontext - das Zeichen, das für die Ziffer Null steht, hat den Hex-Wert 0x30, während das NUL-Zeichen den Hex-Wert 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 macht es klarer.

13voto

Sinan Ünür Punkte 114993

Wenn NULL und 0 als Nullzeigerkonstanten gleichwertig sind, welche sollte ich verwenden? in der C-FAQ-Liste geht auch auf dieses Problem ein:

C-Programmierer müssen verstehen NULL y 0 a Zeigerkontexten austauschbar sind und dass ein uncast 0 ist vollkommen akzeptabel. Jede Verwendung von NULL (im Gegensatz zu 0 ) eine sanfte Erinnerung daran sein, dass ein Zeiger beteiligt ist; Programmierer sollten sich nicht auf ihn verlassen (entweder für ihrem eigenen Verständnis oder dem des des Compilers) für dist 0 von Ganzzahl 0 's.

Es ist nur in Zeigerkonten NULL y 0 gleichwertig sind. NULL s nicht verwendet werden, wenn eine andere Art von 0 ist erforderlich, auch wenn es funktionieren könnte, denn damit wird die falsche stilistische Botschaft. (Außerdem erlaubt ANSI die Definition von NULL t ((void *)0) die nicht funktionieren wird in Nicht-Zeiger-Kontexten überhaupt nicht funktioniert). In verwenden Sie insbesondere nicht NULL w ASCII-Nullzeichen ( NUL ) Geben Sie Ihre eigene Definition an

#define NUL '\0'

wenn Sie müssen.

6voto

Eugene Yokota Punkte 92703

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

"Nullzeichen (NUL)" ist am einfachsten auszuschließen. '\0' ist ein wörtliches Zeichen. In C ist es implementiert als int ist also dasselbe wie 0, was von INT_TYPE_SIZE . In C++ ist das Zeichenliteral implementiert als char was 1 Byte entspricht. Dies ist normalerweise anders als NULL o 0 .

Nächste, NULL ist ein Zeigerwert, der angibt, dass eine Variable nicht auf einen Adressraum zeigt. Abgesehen von der Tatsache, dass er in der Regel als Nullen implementiert wird, muss er in der Lage sein, den gesamten Adressraum der Architektur auszudrücken. So ist NULL auf einer 32-Bit-Architektur (wahrscheinlich) 4 Byte und auf einer 64-Bit-Architektur 8 Byte groß. Dies hängt von der Implementierung von C ab.

Schließlich ist die wörtliche 0 ist vom Typ int die eine Größe von INT_TYPE_SIZE . Der Standardwert von INT_TYPE_SIZE kann je nach Architektur unterschiedlich sein.

Apple 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 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       ?

Editar : Mehr über den wörtlichen Charakter hinzugefügt.

#include <stdio.h>

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

Der obige Code liefert 4 bei gcc und 1 bei g++.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X