Darf ich den NULL
Zeiger als Ersatz für den Wert von verwenden 0
?
Oder ist daran etwas falsch?
Wie zum Beispiel:
int i = NULL;
als Ersatz für:
int i = 0;
Als Experiment habe ich folgenden Code kompiliert:
#include <stdio.h>
int main(void)
{
int i = NULL;
printf("%d",i);
return 0;
}
Ausgabe:
0
In der Tat gibt es mir diese Warnung, die für sich genommen völlig richtig ist:
warning: initialization makes integer from pointer without a cast [-Wint-conversion]
aber das Ergebnis ist immer noch gleichwertig.
- Überquere ich damit "Undefiniertes Verhalten"?
- Ist eine Verwendung
NULL
auf diese Weise zulässig ? - Ist etwas falsch daran,
NULL
einen numerischen Wert in arithmetischen Ausdrücken zu verwenden? - Und was ist das Ergebnis und Verhalten in C ++ für diesen Fall?
Ich habe die Antworten liest Was ist der Unterschied zwischen NULL, ‚\ 0‘ und 0 zu wissen , was der Unterschied zwischen NULL
, \0
und 0
ist, aber ich habe nicht die prägnanten Informationen von dort erhalten, wenn es durchaus zulässig ist und auch Recht auf Verwendung NULL
als Wert, mit dem in Aufgaben und anderen arithmetischen Operationen gearbeitet werden soll.
Antworten:
Nein , das ist nicht sicher.
NULL
ist eine Nullzeigerkonstante, die einen Typ haben könnteint
, aber typischer einen Typvoid *
(in C) hat oder auf andere Weise nicht direkt einerint
(in C ++> = 11) zuweisbar ist . In beiden Sprachen können Zeiger in Ganzzahlen konvertiert werden, sie sehen jedoch nicht vor, dass solche Konvertierungen implizit durchgeführt werden (obwohl einige Compiler dies als Erweiterung bereitstellen). Obwohl es üblich ist, einen Nullzeiger in eine Ganzzahl zu konvertieren, um den Wert 0 zu erhalten, garantiert der Standard dies nicht. Wenn Sie eine Konstante mit Typint
und Wert 0 möchten, buchstabieren Sie sie0
.Ja, bei jeder Implementierung, bei
NULL
der ein Wert mit dem Typvoid *
oder einer anderen nicht direkt zuweisbaren erweitert wirdint
. Der Standard definiert nicht das Verhalten Ihrer Zuweisung bei einer solchen Implementierung, daher ist sein Verhalten undefiniert.Es ist ein schlechter Stil und wird auf einigen Systemen und unter bestimmten Umständen kaputt gehen. Insofern Sie anscheinend GCC verwenden, würde es in Ihrem eigenen Beispiel brechen, wenn Sie mit der
-Werror
Option kompilieren .Ja. Es ist nicht garantiert, dass überhaupt ein numerischer Wert vorliegt. Wenn Sie 0 meinen, schreiben Sie 0, was nicht nur gut definiert, sondern auch kürzer und klarer ist.
Die C ++ - Sprache ist bei Konvertierungen strenger als C und hat andere Regeln für
NULL
, aber auch dort können Implementierungen Erweiterungen bereitstellen. Wenn du wieder 0 meinst, solltest du das schreiben.quelle
void *
" nur für Cvoid *
gilt. Dies ist kein zulässiger Typ für C ++ (da Sievoid*
keinem anderen Zeigertyp zuweisen können). In C ++ 89 und C ++ 03NULL
muss es tatsächlich vom Typ seinint
, in späteren Versionen kann es jedoch sein (und ist es normalerweise)nullptr_t
.void*
inint
ein undefiniertes Verhalten ist. Es ist nicht; Es handelt sich um ein implementierungsspezifisches Verhalten.NULL
ist eine Nullzeigerkonstante. In C könnte es sich um einen ganzzahligen konstanten Ausdruck mit Wert0
oder einen solchen Ausdruck handelnvoid*
, wobei letzterer wahrscheinlicher ist. Das heißt, Sie können nicht davon ausgehen, dass Sie esNULL
austauschbar mit Null verwenden. Zum Beispiel in diesem CodebeispielDas Ersetzen
0
durchNULL
ist kein garantiertes C-Programm, da das Hinzufügen zwischen zwei Zeigern (geschweige denn von verschiedenen Zeigertypen) nicht definiert ist. Es wird eine Diagnose aufgrund einer Einschränkungsverletzung ausgegeben. Die zu addierenden Operanden sind ungültig .Bei C ++ sieht das etwas anders aus. Das Fehlen einer impliziten Konvertierung von
void*
in andere Objekttypen bedeutete, dass diesNULL
historisch wie0
in C ++ - Code definiert wurde. In C ++ 03 könnten Sie wahrscheinlich damit durchkommen. Aber seit C ++ 11 kann es legal alsnullptr
Schlüsselwort definiert werden . Jetzt wird wieder ein Fehler erzeugt, dastd::nullptr_t
Zeigertypen möglicherweise nicht hinzugefügt werden.Wenn
NULL
definiert alsnullptr
dann wird sogar Ihr Experiment ungültig. Es erfolgt keine Konvertierung vonstd::nullptr_t
in eine Ganzzahl. Aus diesem Grund wird es als sicherere Nullzeigerkonstante angesehen.quelle
NULL
in beiden Sprachen verwendet werden.0
eine Nullzeigerkonstante erneut festgelegt: "Offensichtlich als Sop für den gesamten vorhandenen schlecht geschriebenen C-Code, der falsche Annahmen getroffen hat"Die Regeln variieren zwischen den Sprachen und ihren Versionen. In einigen Fällen Sie können und in anderen, können Sie nicht. Egal, du solltest nicht . Wenn Sie Glück haben, warnt Ihr Compiler, wenn Sie es versuchen, oder noch besser, Sie können nicht kompilieren.
In C ++ vor C ++ 11 (Zitat aus C ++ 03):
Es ist wenig sinnvoll, eine Nullzeigerkonstante als Ganzzahl zu verwenden. Jedoch...
Es würde also technisch funktionieren, selbst wenn es unsinnig wäre. Aufgrund dieser Technik können Sie auf schlecht geschriebene Programme stoßen, die missbrauchen
NULL
.Seit C ++ 11 (Zitat aus dem neuesten Entwurf):
A
std::nullptr_t
ist nicht in eine Ganzzahl konvertierbar, daher würde die VerwendungNULL
als Ganzzahl nur bedingt funktionieren, abhängig von den von der Sprachimplementierung getroffenen Entscheidungen.PS
nullptr
ist ein Wert vom Typstd::nullptr_t
. Sofern Sie Ihr Programm nicht zum Kompilieren in Pre-C ++ 11 benötigen, sollten Sie immernullptr
anstelle von verwendenNULL
.C ist etwas anders (Zitate aus C11 Entwurf N1548):
Der Fall ähnelt also dem nach C ++ 11, dh der Missbrauch von
NULL
Werken hängt von den Entscheidungen ab, die von der Sprachimplementierung getroffen werden.quelle
Ja , obwohl Sie je nach Implementierung möglicherweise eine Besetzung benötigen. Aber ja, sonst ist es 100% legitim.
Obwohl es wirklich, wirklich, wirklich schlechter Stil ist (unnötig zu sagen?).
NULL
ist oder war eigentlich nicht C ++, es ist C. Der Standard hat jedoch, wie für viele C-Vermächtnisse, zwei Klauseln ([diff.null] und [support.types.nullptr]), dieNULL
C ++ technisch machen . Es ist eine implementierungsdefinierte Nullzeigerkonstante . Selbst wenn es ein schlechter Stil ist, ist es technisch so C ++ wie es nur sein kann.Wie in der darauf hingewiesen Fußnote könnten mögliche Implementierungen sein
0
oder0L
aber nicht(void*)0
.NULL
könnte natürlich sein (der Standard sagt es nicht ausdrücklich, aber es ist so ziemlich die einzige Wahl, die nach0
oder bleibt0L
)nullptr
. Das ist fast nie der Fall, aber es ist eine rechtliche Möglichkeit.Die Warnung, die der Compiler Ihnen angezeigt hat, zeigt, dass der Compiler tatsächlich nicht kompatibel ist (es sei denn, Sie haben im C-Modus kompiliert). Weil, laut der Warnung, ein Nullzeiger konvertiert wurde (nicht
nullptr
der vonnullptr_t
, der verschieden wäre), so ist anscheinend die Definition vonNULL
tatsächlich(void*)0
, was es möglicherweise nicht ist.In beiden Fällen gibt es zwei mögliche legitime Fälle (dh Compiler nicht defekt). Entweder (der realistische Fall)
NULL
ist so etwas wie0
oder0L
, dann haben Sie "null oder eins" Konvertierungen in eine Ganzzahl, und Sie können loslegen.Oder
NULL
ist in der Tatnullptr
. In diesem Fall haben Sie einen eindeutigen Wert, der Vergleichsgarantien sowie klar definierte Konvertierungen von Ganzzahlen bietet, aber leider nicht in Ganzzahlen. Es hat jedoch eine klar definierte Konvertierung inbool
(resultierend infalse
) undbool
eine klar definierte Konvertierung in eine Ganzzahl (resultierend in0
).Leider sind das zwei Conversions, also nicht innerhalb von "null oder eins", wie in [conv] ausgeführt. Wenn Ihre Implementierung
NULL
als definiert istnullptr
, müssen Sie eine explizite Umwandlung hinzufügen, damit Ihr Code korrekt ist.quelle
Aus der C-FAQ:
quelle
Haftungsausschluss: Ich kenne C ++ nicht. Meine Antwort soll nicht im Kontext von C ++ angewendet werden
'\0'
ist einint
mit dem Wert Null, nur 100% genau wie0
.Im Zusammenhang mit Zeigern ,
0
undNULL
sind zu 100% entspricht:sind alle 100% gleichwertig.
Hinweis zu
ptr + NULL
Der Kontext von
ptr + NULL
ist nicht der von Zeigern. Es gibt keine Definition für das Hinzufügen von Zeigern in der C-Sprache. Zeiger und ganze Zahlen können addiert (oder subtrahiert) werden. Inptr + NULL
wenn entwederptr
oderNULL
ist ein Zeiger, der andere muss eine ganze Zahl, soptr + NULL
effektiv(int)ptr + NULL
oderptr + (int)NULL
je nach den Definitionenptr
undNULL
einige Verhaltensweisen zu rechnen: sie alle arbeitet, Warnung für die Konvertierung zwischen Zeigern und integer, Versagen zu kompilieren, .. .quelle
#define NULL (void *)0
. Sind Sie sicher, dass NULL und Plain 0 zu 100% gleichwertig sind?ptr + NULL
wird nichtNULL
im Zusammenhang mit Zeigern verwendetnullptr
ist, aber((void*)0)
und0
(oder'\0'
) sind im Zusammenhang mit Zeigern gleichwertig ...if (ptr == '\0' /* or equivalent 0, NULL */)
Nein, nicht mehr bevorzugt zu verwenden
NULL
(alte Art der Zeigerinitilisierung).Seit C ++ 11:
Das Schlüsselwort
nullptr
bezeichnet das Zeigerliteral. Es ist ein Wert vom Typ std :: nullptr_t. Es gibt implizite Konvertierungen vonnullptr
in einen Nullzeigerwert eines beliebigen Zeigertyps und eines beliebigen Zeigers in einen Elementtyp. Ähnliche Konvertierungen gibt es für jede Nullzeigerkonstante, die sowohl Werte vom Typstd::nullptr_t
als auch das Makro enthältNULL
.https://en.cppreference.com/w/cpp/language/nullptr
Tatsächlich ist std :: nullptr_t der Typ des Nullzeigerliteral ,
nullptr
. Es ist ein eindeutiger Typ, der selbst kein Zeigertyp oder Zeiger auf den Elementtyp ist.Ausgabe:
quelle