Frage

In den frühen Tagen von C ++, wenn es oben auf C verschraubt wurde, konnte man nicht NULL verwenden, da es als (void*)0 definiert wurde. Sie könnten nicht auf einen Zeiger anderen als void* zuweisen NULL, die es von nutzloser Art gemacht. Damals, es wurde angenommen, dass Sie 0 verwendet (Null) für Null-Zeiger.

Bis zum heutigen Tag habe ich fortgesetzt Null als Null-Zeiger zu verwenden, aber das um mich herum bestehen auf NULL verwenden. Ich persönlich sehe keinen Nutzen Sie einen Namen (NULL) zu einem bestehenden Wert zu geben - und da Ich mag auch Zeiger als Wahrheitswerte testen:

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

dann mit Null macht mehr Sinn (wie in, wenn Sie NULL verwenden, können Sie logisch nicht p && !q verwenden - Sie müssen explizit gegen NULL vergleichen zu können, es sei denn, Sie NULL annehmen Null ist, wobei in diesem Fall, warum Gebrauch NULL)

.

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

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

.
War es hilfreich?

Lösung

Hier ist Stroustrup nehmen auf diese: C ++ Stil und Technik FAQ

  

In C ++ ist die Definition von NULL 0, so gibt es nur einen ästhetischen Unterschied. Ich ziehe es Makros zu vermeiden, so dass ich 0. Ein weiteres Problem bei NULL ist, dass Menschen manchmal fälschlicherweise glauben, dass es anders ist von 0 und / oder nicht einer ganzen Zahl ist. In Pre-Standard-Code, NULL wurde / wird manchmal definiert, um etwas ungeeignet und hatte daher / muss vermieden werden. Das ist weniger häufig in diesen Tagen.

     

Wenn Sie die Null-Zeiger zu nennen haben, rufen Sie es nullptr; das ist, was es ist C ++ 11 hinzugezogen. Dann wird nullptr ein Schlüsselwort sein.

Wie gesagt, nicht Kleinkram.

Andere Tipps

Es gibt einige Argumente (von denen relativ neu ist), die ich widersprechen glaube Bjarne Position zu diesem Thema.

  1. Dokumentation des Vorsatzes

NULL verwenden, kann für die Suche auf seine Verwendung und es zeigt auch, dass der Entwickler wollte einen NULL Zeiger zu verwenden, unabhängig davon, ob sie durch den Compiler als NULL interpretiert wird oder nicht.

  1. Überlastung des Zeigers und 'int' ist relativ selten

Das Beispiel, dass jeder zitiert ist:

void foo(int*);
void foo (int);

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

Aber zumindest meiner Meinung nach, das Problem mit der oben ist nicht, dass wir NULL für die Null-Zeiger-Konstante verwenden, es ist, dass wir Überlastungen von ‚foo‘ haben, die nehmen sehr unterschiedliche Arten von Argumenten. Der Parameter muss einen int sein, als jede andere Art in einem zweideutigen Ruf führen und so eine hilfreiche Compiler-Warnung erzeugen.

  1. Analyse-Tools können TODAY helfen!

Auch in Abwesenheit von C ++ 0x gibt es Werkzeuge zur Verfügung heute, dass überprüfen, ob NULL für Zeiger verwendet wird, und dass 0 für integrale Typen verwendet wird.

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

Dies ist das neueste Argument auf den Tisch. Das Problem der 0 und NULL aktiv für C ++ 0x angesprochen zu werden, und Sie können, dass für jede Implementierung garantieren, dass NULL liefert, die erste Sache, die sie tun, ist:

#define NULL  nullptr

Für diejenigen, die NULL verwenden, anstatt 0, wird die Änderung eine Verbesserung der Typsicherheit mit wenig oder gar keine Mühe - wenn alles, was es auch ein paar Fehler fangen können, wo sie NULL für 0 verwendet haben. Für alle mit 0 heute .... ähm ... naja hoffentlich haben sie eine gute Kenntnis von regulären Ausdrücken ...

Verwenden Sie NULL. NULL zeigt Ihre Absicht. Dass es 0 ist eine Implementierung Detail, das sollte keine Rolle spielen.

Ich hörte mit NULL zugunsten von 0 schon vor langer Zeit (wie auch die meisten anderen Makros). Ich tat dies nicht nur, weil ich Makros so weit wie möglich vermeiden wollte, sondern auch, weil NULL scheint worden zu sein über verwendete in C und C ++ Code. Es scheint, verwendet zu werden, wenn ein 0-Wert benötigt wird, nicht nur für Zeiger.

Auf neue Projekte, ich habe dies in einem Projekt-Header:

static const int nullptr = 0;

Nun, wenn C ++ 0x-konforme Compilern kommen, alles, was ich tun muß, ist diese Zeile zu entfernen. Ein schöner Vorteil davon ist, dass Visual Studio bereits als Schlüsselwort erkennt nullptr und zeigt sie entsprechend.

ich immer wie folgt:

  • NULL für Zeiger
  • '\0' für Zeichen
  • 0.0 für floats und doubles

, wobei 0 täte gut. Es ist eine Frage der Absicht signalisiert. Das heißt, ich bin nicht pingelig es.

    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 von der Geschichte. Sie sollten NULL verwenden, wenn Sie mit Zeigern zu tun hat.

1) Es erklärt Ihre Absicht (nicht ich durch die gesamten Code machen suchen, um herauszufinden, ob eine Variable ein Zeiger oder ein numerischer Typ ist).

2) In bestimmten API-Aufrufe, die variable Argumente erwarten, werden sie einen NULL-Zeiger, um das Ende der Argumentliste verwenden. In diesem Fall mit einem ‚0‘ anstelle von NULL Probleme verursachen kann. Auf einer 64-Bit-Plattform will der va_arg Anruf einen 64-Bit-Zeiger, aber Sie werden nur ein 32-Bit-Integer geben werden. Scheint mir, wie Sie auf den anderen 32-Bit angewiesen sind für Sie auf Null gesetzt werden? Ich habe bestimmte Compiler gesehen (zum Beispiel Intels icpc), die nicht so gnädig ist -. Und dies hat in Laufzeitfehler in Folge

Wenn ich mich richtig erinnere NULL definiert ist anders in den Header, die ich verwendet habe. Für C wird es als (void *) 0 definiert, und für C ++ ist es definiert als nur 0. Der Code sah so etwas wie:

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

Persönlich den NULL-Wert ich immer noch verwendet Null-Zeiger darzustellen, macht es ausdrücklich, dass Sie einen Zeiger, anstatt etwas integralen Typen verwenden. Ja intern der NULL-Wert ist immer noch 0, aber es ist nicht als solche dargestellt.

Außerdem verlasse ich nicht auf die automatische Konvertierung von ganzen Zahlen Boolesche Werte, sondern sie explizit vergleichen.

Zum Beispiel bevorzugen zu verwenden:

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

statt:

if (pointer_value || !integer_value)

Es genügt zu sagen, dass dies alles in C ++ behoben ist 11, wo man einfach nullptr statt NULL verwenden kann, und nullptr_t auch, dass der Typ eines nullptr ist.

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

Nach der Erstellung von C ++ 11, mit seinem neuen nullptr Art haben einige Compiler gestartet beschweren (mit Standardparametern) etwa 0 bis Funktionen mit Zeiger Argumente zu übergeben, weil 0 kein Zeiger ist.

Wenn der Code geschrieben hat, wurde NULL verwenden, eine einfache Suche und ersetzen hätte man durch die Code-Basis durchgeführt, um es zu machen nullptr statt. Wenn Sie mit dem Code geschrieben mit der Wahl von 0 als Zeiger steckt es viel mühsamer ist es zu aktualisieren.

Und wenn Sie jetzt neuen Code schreiben müssen, um die C ++ 03-Standard (und kann nicht verwendet werden nullptr), sollten Sie wirklich nur NULL verwenden. Es wird es viel einfacher für Sie in der Zukunft zu aktualisieren.

Ich verwende in der Regel 0. Ich mag keine Makros, und es gibt keine Garantie, dass einige Drittanbieter-Header Sie verwenden nicht NULL ist neu definieren etwas seltsam.

Sie könnten ein nullptr-Objekt verwenden, wie von Scott Meyers und anderen vorgeschlagen, bis C ++ ein nullptr Schlüsselwort wird:

const // It is a const object...
class nullptr_t 
{
public:
    template<class T>
    operator T*() const // convertible to any type of null non-member pointer...
    { return 0; }

    template<class C, class T>
    operator T C::*() 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 auf einer Maschine, 0 war eine gültige Adresse und NULL wurde als Sonder Oktalwert definiert. Auf dieser Maschine (0! = NULL), so Code wie

char *p;

...

if (p) { ... }

würde nicht funktionieren, wie Sie es erwarten. Man muß schreiben

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

Obwohl ich die meisten Compiler definieren NULL als 0 in diesen Tagen glaube ich, noch die Lehre aus diesen Jahren erinnere mich vor. NULL ist nicht unbedingt 0

Ich denke, den Standard garantiert, dass NULL == 0, so können Sie entweder tun können. Ich ziehe es NULL, weil es Ihre Absicht dokumentiert.

0 oder NULL verwenden die gleiche Wirkung haben.

Allerdings bedeutet das nicht, dass sie beide gute Programmierpraktiken sind. Da gibt es keinen Unterschied in der Leistung, eine Low-Level-aware Option über einen Agnostiker / abstract alternative Wahl ist eine schlechte Programmierpraxis. Hilfe Leser Ihres Codes verstehen Ihr Denkprozess .

NULL, 0, 0.0, '\ 0', 0x00 und whatelse alle auf dasselbe übersetzen, aber sind verschiedene logische Einheiten in Ihrem Programm. Sie sollten als solche verwendet werden. NULL ist ein Zeiger, 0 Menge ist, 0x0 ist ein Wert, deren Bits interessant usw. Sie würden nicht ‚\ 0‘ zu einem Zeiger zuweisen, ob es kompiliert oder nicht.

Ich weiß, dass einige Gemeinden in gründliche fördern die Kenntnis der Nachweis einer Umgebung durch die Umwelt der Verträge zu brechen. Verantwortlich Programmierer jedoch wartbaren Code machen und solche Praktiken halten aus ihrem Code.

Seltsam, niemand, einschließlich Stroustroup erwähnt, dass. Während viel über Standards und Ästhetik spricht niemand bemerkt, dass es gefährlich 0 in NULL Statt zu verwenden, zum Beispiel in variable Argumentliste auf der Architektur, in der sizeof(int) != sizeof(void*). Wie Stroustroup, ziehe ich 0 aus ästhetischen Gründen, aber man muss aufpassen, nicht sein, es zu benutzen, wo seine Art mehrdeutig sein könnte.

Ich versuche, die ganze Frage zu vermeiden, indem sie unter Verwendung von C ++ Referenzen, soweit möglich. Anstatt

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

Sie können oft in der Lage sein zu schreiben

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

Natürlich ist dies nicht immer funktioniert; aber Null-Zeiger kann überstrapaziert werden.

Ich bin mit Stroustrup auf diesem :-) Da NULL nicht Teil der Sprache ist, ziehe ich es 0 verwenden.

Meistens persönliche Präferenz, obwohl könnte man das Argument, dass NULL es ganz offensichtlich macht, dass das Objekt einen Zeiger ist, die derzeit nicht auf irgendetwas nicht zeigen, z.

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

IIRC, wird der Standard nicht NULL erfordert 0 sein, also mit was auch immer in definiert wird ist wahrscheinlich am besten für Ihren Compiler.

Eine weitere Facette auf das Argument ist, ob Sie logische Vergleiche (implizite Umwandlung zu bool) oder explizit überprüfen gegen NULL verwenden sollte, aber das kommt unten als auch auf die Lesbarkeit.

Ich ziehe es NULL zu verwenden, da es deutlich macht, dass Ihre Absicht ist, stellt der Wert ein Zeiger nicht ein arithmetischer Wert. Die Tatsache, dass es sich um einen Makro ist, ist bedauerlich, aber da es so weit tief verwurzelt ist es wenig Gefahr (es sei denn, jemand etwas wirklich boneheaded tut). Ich möchte es ein Stichwort von Anfang an, aber was kann man tun?

Das heißt, ich habe kein Problem mit Zeigern als Wahrheitswerte in sich selbst verwenden. Genau wie bei NULL, es ist ein tief verwurzeltes Idiom.

C ++ 09 das die nullptr Konstrukt hinzufügen, die ich denke, ist längst überfällig.

Ich benutze immer 0. Nicht für jede wahre Grund gedacht, nur weil, wenn ich zum ersten Mal das Lernen C war ++ ich etwas lesen, die unter Verwendung von 0 empfohlen und ich habe gerade immer so gemacht. Theoretisch könnte es eine Verwirrung Problem in Lesbarkeit sein, aber in der Praxis haben, wenn ich nie über eine solche Frage in Tausenden von Mannstunden und Millionen von Codezeilen kommen. Wie Stroustrup sagt, es ist wirklich nur ein persönliches ästhetisches Problem, bis der Standard nullptr wird.

Jemand hat mir einmal gesagt ... Ich werde NULL bis 69 neu zu definieren Seitdem ich es nicht verwenden: P

Es macht Ihren Code ziemlich anfällig.

Edit:

Nicht alles in der Norm ist perfekt. Das Makro NULL ist eine Implementierung definiert C ++ Null-Zeiger-Konstante nicht vollständig kompatibel mit Makro C NULL, was neben der Art von Fehlern Werkzeug implizit konvertiert es in einem nutzlosen und anfällig versteckt.

NULL verhält sich nicht als Null-Zeiger, sondern als O / OL wörtlich zu nehmen.

Sag mir nächstes Beispiel ist nicht verwirrend:

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

Ist wegen all das, was in dem neuen Standard erscheint std :: nullptr_t

Wenn Sie nicht möchten, dass für den neuen Standard warten und wollen ein nullptr verwenden möchten, verwenden mindestens ein anständiges wie der Vorschlag Meyers (siehe jon.h Kommentar).

Nun, ich argumentiere, für nicht mit 0 oder NULL-Zeiger überhaupt, wann immer möglich.

Mit ihnen wird früher oder später zu Segmentierung Fehler im Code führen. In meiner Erfahrung und Zeiger in gereral ist eine der größten Fehlerquelle in C ++

auch, es führt zu „wenn-nicht-null“ Aussagen ganzen Code. Viel schöner, wenn Sie auf immer einen gültigen Zustand verlassen können.

Es gibt fast immer eine bessere Alternative.

einen Zeiger auf 0 zu setzen ist einfach nicht so klar. Vor allem, wenn Sie kommen, eine andere Sprache als C ++. Dazu gehören C sowie Javascript.

Ich habe vor kurzem mit einigen Code delt wie folgt:

virtual void DrawTo(BITMAP *buffer) =0;

für rein virtuelle Funktion zum ersten Mal. Ich dachte, es etwas Magie jiberjash für eine Woche. Als ich merkte, war es im Grunde nur die Funktion Zeiger auf einen null Einstellung (als virtuelle Funktionen werden in den meisten Fällen für C nur Zeiger funktionieren ++) Ich trat mich.

virtual void DrawTo(BITMAP *buffer) =null;

gewesen wäre weniger verwirrend als das basterdation ohne den richtigen Abstand zu meinem neuen Augen. Eigentlich frage ich mich, warum C ++ nicht Klein null verwenden viel wie es jetzt Klein falsch und wahr employes.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top