Verwenden Sie NULL oder 0 (Null) für pointers in C ++?

In den frühen Tagen von C ++, als es über C geschraubt wurde, konnten Sie NULL nicht verwenden, wie es als (void*)0 . Sie konnten keinem anderen pointers als void* NULL zuweisen, was es nutzlos machte. Damals wurde angenommen, dass Sie 0 (Null) für Nullzeiger verwendet haben.

Bis heute habe ich weiterhin Null als Null-pointers verwendet, aber die um mich herum bestehen darauf, NULL . Ich persönlich sehe keinen Vorteil darin, einem existierenden Wert einen Namen ( NULL ) zu geben – und da ich auch gerne pointers als Wahrheitswerte teste:

 if (p && !q) do_something(); 

dann macht die Verwendung von null mehr Sinn (wie wenn Sie NULL , können Sie nicht logisch p && !q – Sie müssen explizit mit NULL vergleichen, es sei denn, Sie nehmen an, dass NULL Null ist. In diesem Fall verwenden Sie NULL ).

Gibt es einen objektiven Grund, Null über NULL (oder umgekehrt) zu bevorzugen, oder ist alles nur persönliche Vorliebe?

Edit: Ich sollte hinzufügen (und ursprünglich zu sagen), dass mit RAII und Ausnahmen, verwende ich selten Null / NULL-pointers, aber manchmal Sie brauchen sie immer noch.

Solutions Collecting From Web of "Verwenden Sie NULL oder 0 (Null) für pointers in C ++?"

Hier ist Stroustrups Antwort: C ++ Style und Technique FAQ

In C ++ ist die Definition von NULL 0, es gibt also nur einen ästhetischen Unterschied. Ich bevorzuge es, Makros zu vermeiden, also benutze ich 0. Ein weiteres Problem mit NULL ist, dass Leute irrtümlich manchmal glauben, dass es sich von 0 und / oder keine ganze Zahl unterscheidet. In Vor-Standard-Code wurde NULL manchmal als etwas unpassend definiert und musste daher vermieden werden. Das ist heutzutage weniger üblich.

Wenn Sie den Nullzeiger benennen nullptr , nennen Sie ihn nullptr ; so heißt es in C ++ 11. Dann wird nullptr ein Schlüsselwort sein.

Das heißt, schwitzen Sie nicht die kleinen Sachen.

Es gibt ein paar Argumente (von denen eine relativ neu ist), die meiner Meinung nach Bjarnes Position zu diesem Thema widersprechen.

  1. Dokumentation der Absicht

Wenn Sie NULL können Sie nach eigenen Suchvorgängen suchen. Außerdem wird hervorgehoben, dass der Entwickler einen NULL pointers verwenden möchte , unabhängig davon, ob er vom Compiler als NULL interpretiert wird oder nicht.

  1. Eine Überladung von pointers und ‘int’ ist relativ selten

Das Beispiel, das jeder zitiert, ist:

 void foo(int*); void foo (int); void bar() { foo (NULL); // Calls 'foo(int)' } 

Meiner Meinung nach ist das Problem mit dem Obigen jedoch nicht, dass wir NULL für die Null-pointers-Konstante verwenden, sondern dass wir Überladungen von ‘foo’ haben, die sehr unterschiedliche Arten von Argumenten verwenden. Der Parameter muss auch ein int sein, da jeder andere Typ zu einem mehrdeutigen Aufruf führt und so eine hilfreiche Compiler-Warnung generiert.

  1. Analyse-Tools können HEUTE helfen!

Sogar in Abwesenheit von C ++ 0x gibt es heute verfügbare Tools, die verifizieren, dass NULL für pointers verwendet wird und dass 0 für ganzzahlige Typen verwendet wird.

  1. C ++ 11 wird einen neuen std::nullptr_t Typ haben.

Dies ist das neueste Argument für die Tabelle. Das Problem von 0 und NULL wird aktiv für C ++ 0x behandelt, und Sie können garantieren, dass für jede Implementierung, die NULL bereitstellt, die allererste Sache, die sie tun, ist:

 #define NULL nullptr 

Für diejenigen, die NULL anstelle von 0 , wird die Änderung eine Verbesserung in der Typsicherheit mit wenig oder keiner Anstrengung sein – wenn überhaupt, kann es auch ein paar Bugs finden, wo sie NULL für 0 . Für jeden, der heute 0 … ähm … naja, hoffentlich haben sie gute Kenntnisse von regulären Ausdrücken …

Verwenden Sie NULL. NULL zeigt deine Absicht an. Dass es 0 ist, ist ein Implementierungsdetail, das keine Rolle spielen sollte.

Ich habe vor langer Zeit NULL zugunsten von 0 aufgehört (wie auch die meisten anderen Makros). Ich tat dies nicht nur, weil ich Makros so viel wie möglich vermeiden wollte, sondern auch, weil NULL in C- und C ++ – Code übermäßig verwendet wurde. Es scheint immer dann verwendet zu werden, wenn ein 0-Wert benötigt wird, nicht nur für pointers.

Bei neuen Projekten lege ich das in einen Projektheader:

 static const int nullptr = 0; 

Jetzt, wenn C ++ 0x-kompatible Compiler ankommen, muss ich nur diese Zeile entfernen. Ein schöner Vorteil davon ist, dass Visual Studio bereits nullptr als Keyword erkennt und entsprechend hervorhebt.

Ich benutze immer:

  • NULL für pointers
  • '\0' für Zeichen
  • 0.0 für Floats und Doubles

wo 0 gut wäre. Es ist eine Frage der Signalisierungsabsicht. Das heißt, ich bin nicht anal darüber.

  cerr < < sizeof(0) << endl; cerr << sizeof(NULL) << endl; cerr << sizeof(void*) << endl; ============ On a 64-bit gcc RHEL platform you get: 4 8 8 ================ 

Die Moral der Geschichte. Sie sollten NULL verwenden, wenn Sie mit pointersn zu tun haben.

1) Es erklärt Ihre Absicht (lassen Sie mich nicht Ihren gesamten Code durchsuchen, um herauszufinden, ob eine Variable ein pointers oder ein numerischer Typ ist).

2) In bestimmten API-Aufrufen, die variable Argumente erwarten, verwenden sie einen NULL-pointers, um das Ende der Argumentliste anzuzeigen. In diesem Fall kann die Verwendung einer '0' anstelle von NULL zu Problemen führen. Auf einer 64-Bit-Plattform benötigt der Aufruf va_arg einen 64-Bit-pointers, aber Sie übergeben nur eine 32-Bit-Ganzzahl. Scheint mir, als würden Sie sich darauf verlassen, dass die anderen 32 Bits für Sie auf Null gesetzt werden? Ich habe bestimmte Compiler (zB Intels iccp) gesehen, die nicht so gnädig sind - und das hat zu Laufzeiterrorsn geführt.

Wenn ich mich richtig erinnere, ist NULL in den Kopfzeilen, die ich benutzt habe, anders definiert. Für C ist es definiert als (void *) 0, und für C ++ wird es als 0 definiert. Der Code sah ungefähr so ​​aus:

 #ifndef __cplusplus #define NULL (void*)0 #else #define NULL 0 #endif 

Persönlich benutze ich immer noch den Nullwert, um Nullzeiger darzustellen, es macht deutlich, dass Sie einen pointers anstelle eines ganzzahligen Typs verwenden. Ja intern ist der NULL-Wert immer noch 0, aber er wird nicht als solcher dargestellt.

Außerdem verlasse ich mich nicht auf die automatische Umwandlung von ganzen Zahlen in boolesche Werte, sondern vergleiche sie explizit.

Zum Beispiel bevorzugen Sie zu verwenden:

 if (pointer_value != NULL || integer_value == 0) 

eher, als:

 if (pointer_value || !integer_value) 

Es genügt zu sagen, dass dies alles in C ++ 11 behoben wurde, wo man einfach nullptr anstelle von NULL , und auch nullptr_t , was der Typ eines nullptr .

Ich würde sagen, Geschichte hat gesprochen und diejenigen, die für die Verwendung von 0 (Null) argumentierten, waren falsch (einschließlich Bjarne Stroustrup). Die Argumente für 0 waren meist Ästhetik und “persönliche Präferenz”.

Nach der Erstellung von C ++ 11 mit seinem neuen nullptr-Typ haben einige Compiler damit begonnen, sich (mit Standardparametern) über die Übergabe von 0 an functionen mit pointersargumenten zu beschweren, da 0 kein pointers ist.

Wenn der Code mit NULL geschrieben worden wäre, könnte ein einfaches Suchen und Ersetzen durch die Codebasis durchgeführt worden sein, um stattdessen nullptr zu machen. Wenn Sie mit Code, der mit der Wahl von 0 als pointers geschrieben wurde, stecken bleiben, ist es viel mühsamer, ihn zu aktualisieren.

Und wenn Sie jetzt neuen Code in den C ++ 03-Standard schreiben müssen (und nullptr nicht verwenden können), sollten Sie NULL verwenden. Es wird Ihnen die Aktualisierung in Zukunft wesentlich erleichtern.

Normalerweise verwende ich 0. Ich mag keine Makros, und es gibt keine Garantie, dass einige Header von Drittanbietern, die Sie verwenden, NULL nicht als etwas Seltsames definieren.

Sie könnten ein von Scott Meyers und anderen vorgeschlagenes nullptr-Objekt verwenden, bis C ++ ein Schlüsselwort nullptr erhält:

 const // It is a const object... class nullptr_t { public: template operator T*() const // convertible to any type of null non-member pointer... { return 0; } template operator TC::*() const // or any type of null member pointer... { return 0; } private: void operator&() const; // Can't take address of nullptr } nullptr = {}; 

Google “nullptr” für weitere Informationen.

Ich habe einmal an einer Maschine gearbeitet, wo 0 eine gültige Adresse war und NULL als ein spezieller Oktalwert definiert wurde. Auf dieser Maschine (0! = NULL), also Code wie

 char *p; ... if (p) { ... } 

würde nicht so funktionieren, wie du es erwartest. Du musstest schreiben

 if (p != NULL) { ... } 

Obwohl ich glaube, dass die meisten Compiler NULL als 0 definieren, erinnere ich mich noch an die Lektion aus diesen Jahren: NULL ist nicht notwendigerweise 0.

Ich denke, der Standard garantiert, dass NULL == 0, also können Sie beides tun. Ich bevorzuge NULL, weil es deine Absicht dokumentiert.

Die Verwendung von 0 oder NULL hat den gleichen Effekt.

Das bedeutet jedoch nicht, dass sie beide gute Programmierpraktiken sind. Angesichts der Tatsache, dass es keinen Unterschied in der performance gibt, ist die Wahl einer Low-Level-aware-Option gegenüber einer agnostic / abstract-Alternative eine schlechte Programmierpraxis. Hilf den Lesern deines Codes, deinen Denkprozess zu verstehen .

NULL, 0, 0.0, ‘\ 0’, 0x00 und whatelse übersetzen alle zur selben Sache, sind aber unterschiedliche logische Einheiten in Ihrem Programm. Sie sollten als solche verwendet werden. NULL ist ein pointers, 0 ist eine Größe, 0x0 ist ein Wert, dessen Bits interessant sind usw. Sie würden keinem pointers ‘\ 0’ zuweisen, ob er kompiliert oder nicht.

Ich weiß, dass einige Gemeinden dazu ermutigt werden, ein detailliertes Wissen über eine Umwelt zu demonstrieren, indem sie die Verträge der Umwelt brechen. Verantwortliche Programmierer erstellen jedoch wartbaren Code und halten solche Praktiken aus ihrem Code heraus.

Seltsam, niemand, einschließlich Stroustroup erwähnt das. Während man viel über Standards und Ästhetik redet, fällt niemandem auf, dass es gefährlich ist , 0 NULL zu verwenden, zum Beispiel in der Variablenargumentliste auf der Architektur, wo sizeof(int) != sizeof(void*) . Wie Stroustroup bevorzuge ich aus ästhetischen Gründen 0 , aber man muss vorsichtig sein, es nicht zu verwenden, wo sein Typ mehrdeutig ist.

Ich versuche, die ganze Frage zu vermeiden, indem ich, wenn möglich, C ++ – Referenzen verwende. Eher, als

 void foo(const Bar* pBar) { ... } 

Sie könnten oft schreiben können

 void foo(const Bar& bar) { ... } 

Natürlich funktioniert das nicht immer. Nullzeiger können jedoch überstrapaziert werden.

Ich bin bei Stroustrup dabei 🙂 Da NULL kein Teil der Sprache ist, bevorzuge ich 0.

Meistens persönliche Präferenz, obwohl man das Argument machen könnte, dass NULL es ziemlich offensichtlich macht, dass das Objekt ein pointers ist, der momentan auf nichts zeigt, z

 void *ptr = &something; /* lots o' code */ ptr = NULL; // more obvious that it's a pointer and not being used 

IIRC, der Standard erfordert NULL nicht 0 zu sein, also ist es am besten für Ihren Compiler, das zu verwenden, was in definiert ist.

Eine weitere Facette des Arguments ist, ob Sie logische Vergleiche (implizite Umwandlung in bool) oder eine explizite Überprüfung gegen NULL verwenden sollten, aber das kommt auch auf die Lesbarkeit an.

Ich bevorzuge es, NULL zu verwenden, da es klarstellt, dass Ihre Absicht der Wert ist, der einen pointers und keinen arithmetischen Wert darstellt. Die Tatsache, dass es ein Makro ist, ist bedauerlich, aber da es so tief verwurzelt ist, gibt es wenig Gefahr (es sei denn, jemand macht etwas wirklich Bockiges). Ich wünschte, es wäre von Anfang an ein Schlüsselwort, aber was können Sie tun?

Das heißt, ich habe kein Problem damit, pointers als Wahrheitswerte zu verwenden. Genau wie bei NULL ist es ein tief verwurzeltes Idiom.

C ++ 09 fügt das Konstrukt nullptr hinzu, von dem ich denke, dass es längst überfällig ist.

Ich benutze immer 0. Nicht für irgendeinen wirklich durchdachten Grund, nur weil ich, als ich das erste Mal C ++ gelernt habe, etwas gelesen habe, das die Verwendung von 0 empfiehlt, und ich habe es immer nur so gemacht. Theoretisch könnte es bei der Lesbarkeit Verwirrung geben, aber in der Praxis bin ich in Tausenden von Arbeitsstunden und Millionen von Codezeilen nie auf ein solches Problem gestoßen. Wie Stroustrup sagt, ist es nur ein persönliches ästhetisches Problem, bis der Standard zu nullptr wird.

Jemand hat es mir einmal gesagt … Ich werde NULL bis 69 neu definieren. Seitdem benutze ich es nicht mehr: P

Es macht Ihren Code ziemlich anfällig.

Bearbeiten:

Nicht alles im Standard ist perfekt. Der Makro-NULL ist eine implementation-definierte C ++ – Nullzeiger-Konstante, die nicht vollständig mit dem C-NULL-Makro kompatibel ist, was neben dem Typ, der implizit versteckt, in ein nutzloses und errorsanfälliges Werkzeug konvertiert.

NULL verhält sich nicht als Nullzeiger, sondern als O / OL-Literal.

Sag mir nächstes Beispiel ist nicht verwirrend:

 void foo(char *); void foo(int); foo(NULL); // calls int version instead of pointer version! 

Aus diesem Grund erscheint im neuen Standard std :: nullptr_t

Wenn Sie nicht auf den neuen Standard warten wollen und ein nullptr verwenden möchten, verwenden Sie mindestens einen anständigen wie den von Meyers vorgeschlagenen (siehe jon.h Kommentar).

Nun, ich plädiere dafür, wann immer möglich keine Null- oder Nullzeiger zu verwenden.

Ihre Verwendung führt früher oder später zu Segmentierungserrorsn in Ihrem Code. Nach meiner Erfahrung ist dies und pointers in gereral eine der größten Fehlerquellen in C ++

Außerdem führt es zu “if-not-null” -statementen in Ihrem gesamten Code. Viel schöner, wenn Sie sich immer auf einen gültigen Zustand verlassen können.

Es gibt fast immer eine bessere Alternative.

Einen pointers auf 0 zu setzen ist einfach nicht klar. Vor allem, wenn Sie eine andere Sprache als C ++ verwenden. Dies beinhaltet sowohl C als auch Javascript.

Ich dont vor kurzem mit etwas Code wie folgt:

virtual void DrawTo(BITMAP *buffer) =0;

für rein virtuelle function zum ersten Mal. Ich dachte, es wäre eine Woche lang ein magischer Jiberjash. Als ich feststellte, dass der functionszeiger im Grunde nur auf null (da virtuelle functionen in C ++ nur functionszeiger sind), habe ich mich selbst getreten.

virtual void DrawTo(BITMAP *buffer) =null;

wäre weniger verwirrend gewesen als diese Basterdation ohne richtigen Abstand zu meinen neuen Augen. Tatsächlich frage ich mich, warum C ++ nicht Kleinbuchstaben null ähnlich wie Kleinbuchstaben falsch und wahr jetzt.