Verwenden Sie NULL oder 0 (Null) für Zeiger in C++?
Lesezeit: 9 Minuten
camh
In den frühen Tagen von C++, als es auf C geschraubt wurde, konnten Sie NULL nicht so verwenden, wie es definiert wurde (void*)0. Sie können keinem anderen Zeiger als NULL zuweisen void*, was es irgendwie nutzlos machte. Damals wurde es akzeptiert, dass Sie es benutzten 0 (Null) für Nullzeiger.
Bis zum heutigen Tag habe ich weiterhin Null als Nullzeiger verwendet, aber meine Mitmenschen bestehen darauf NULL. Ich persönlich sehe keinen Vorteil darin, einen Namen zu nennen (NULL) auf einen vorhandenen Wert – und da ich auch gerne Pointer als Wahrheitswerte teste:
if (p && !q)
do_something();
dann ist die Verwendung von null sinnvoller (als ob Sie verwenden NULLkönnen Sie nicht logisch verwenden p && !q – Sie müssen explizit vergleichen NULLes sei denn, Sie vermuten NULL Null ist, warum in diesem Fall verwenden NULL).
Gibt es einen objektiven Grund, Null gegenüber NULL (oder umgekehrt) zu bevorzugen, oder ist alles nur eine persönliche Präferenz?
Bearbeiten: Ich sollte hinzufügen (und ursprünglich sagen), dass ich bei RAII und Ausnahmen selten Null-/NULL-Zeiger verwende, aber manchmal braucht man sie trotzdem.
Warten Sie, muss ein Nullzeiger nicht als falsch ausgewertet werden, unabhängig davon, ob null intern null ist oder nicht?
In C++ ist die Definition von NULL 0 ist, also gibt es nur einen ästhetischen Unterschied. Ich ziehe es vor, Makros zu vermeiden, also verwende ich 0. Ein weiteres Problem mit NULL ist, dass die Leute manchmal fälschlicherweise glauben, dass es sich von 0 unterscheidet und / oder keine ganze Zahl ist. Im Vorstandardcode, NULL wurde/wird manchmal zu etwas Ungeeignetem definiert und musste/muss daher vermieden werden. Das ist heutzutage weniger üblich.
Wenn Sie den Nullzeiger benennen müssen, rufen Sie ihn auf nullptr; so heißt es in C++11. Dann, nullptr wird ein Schlüsselwort sein.
Das heißt, schwitzen Sie nicht die kleinen Sachen.
Bjarne schrieb dies, bevor C++ 0x anfing, an einem neuen Nulltyp zu arbeiten. Es wird der Fall sein, dass NULL für diesen Typ verwendet wird, wenn er für eine Plattform verfügbar ist, und ich denke, Sie werden eine C-Änderung im allgemeinen Konsens darüber sehen.
– Richard Corden
7. Oktober 2008 um 9:49 Uhr
Richard Korden
Es gibt ein paar Argumente (von denen eines relativ neu ist), die meines Erachtens Bjarnes Position diesbezüglich widersprechen.
Dokumentation der Absicht
Verwenden NULL ermöglicht die Suche nach seiner Verwendung und hebt auch hervor, dass der Entwickler gesucht ein verwenden NULL Zeiger, unabhängig davon, ob er vom Compiler als interpretiert wird NULL oder nicht.
Überladung von Zeiger und ‘int’ ist relativ selten
Zumindest meiner Meinung nach besteht das Problem mit dem oben Gesagten jedoch nicht darin, dass wir verwenden NULL für die Nullzeigerkonstante: Wir haben Überladungen von foo() die sehr unterschiedlich argumentieren. Der Parameter muss ein sein int auch, da jeder andere Typ zu einem mehrdeutigen Aufruf führt und somit eine hilfreiche Compiler-Warnung generiert.
Analysetools können HEUTE helfen!
Selbst ohne C++0x gibt es heute Tools, die das verifizieren NULL wird für Zeiger verwendet, und so weiter 0 wird für ganzzahlige Typen verwendet.
Dies ist das neueste Argument in der Tabelle. Das Problem von 0 und NULL wird aktiv für C++0x adressiert, und Sie können dies für jede bereitgestellte Implementierung garantieren NULLdas allererste, was sie tun werden, ist:
#define NULL nullptr
Für diejenigen, die verwenden NULL eher, als 0wird die Änderung eine Verbesserung der Typsicherheit mit wenig oder gar keinem Aufwand sein – wenn überhaupt, kann es auch ein paar Fehler geben, wo sie verwendet wurden NULL zum 0. Für alle, die es verwenden 0 heute… na ja, hoffentlich haben sie gute Kenntnisse über reguläre Ausdrücke…
Das sind einige ziemlich gute Punkte, muss ich zugeben. Ich bin froh, dass C++ 0x einen Nulltyp haben wird, ich denke, das wird eine Menge Sachen sauberer machen.
– Rauben
7. Oktober 2008 um 14:02 Uhr
@Richard, warum nicht das Gegenteil tun? Sie können Meyers nullptr_t verwenden, wenn 0x verfügbar wird, entfernen Sie die #include und immer auf der sicheren Seite bleiben.
– fnieto – Fernando Nieto
15. November 2009 um 9:18 Uhr
#define NULL nullptr scheint gefährlich. Zum Guten oder Schlechten verwendet viel Legacy-Code NULL für andere Dinge als 0. Zum Beispiel werden Handles oft als ein ganzzahliger Typ implementiert und auf gesetzt NULL ist nicht ungewöhnlich. Ich habe sogar Missbrauch wie Konsum gesehen NULL ein setzen char zu einem Nullterminator.
– Adrian McCarthy
1. Mai 2012 um 22:41 Uhr
@AdrianMcCarthy: Ich würde nur sagen, dass es gefährlich war, wenn die Gefahr bestand, dass der Code stillschweigend kompiliert wird und eine andere Bedeutung hat. Ich bin mir ziemlich sicher, dass dies nicht der Fall ist, sodass tatsächlich alle falschen Verwendungen von NULL erkannt würden.
– Richard Corden
2. Mai 2012 um 14:40 Uhr
@RichardCorden: Ähm, das setzt voraus, dass diese anderen Verwendungen von NULL sind eigentlich falsch. Viele APIs werden seit langem verwendet NULL mit Griffen, und das ist tatsächlich die dokumentierte Verwendung mit vielen von ihnen. Es ist nicht pragmatisch, diese plötzlich zu brechen und zu erklären, dass sie es falsch machen.
– Adrian McCarthy
3. Mai 2012 um 22:41 Uhr
Verwenden Sie NULL. NULL zeigt Ihre Absicht. Dass es 0 ist, ist ein Implementierungsdetail, das keine Rolle spielen sollte.
0 ist kein Implementierungsdetail. Der Standard definiert 0 als ein beliebiges Bitmuster, das einen Nullzeiger darstellt.
– Ferruccio
10. Dezember 2008 um 21:01 Uhr
Als ob ..!! Alter, C++ ist eine Low-Level-Sprache! Verwenden Sie 0, es ist eine bekannte Redewendung.
– Hasen
30. März 2009 um 3:20 Uhr
Ich verstehe, dass es ein Teil des Standards ist. Es ist ein Implementierungsdetail, soweit es um das Lesen des Codes geht. Der Leser sollte “NULL-Zeiger” denken, nicht “0, was in diesem Fall NULL-Zeiger bedeutet, keine Zahl, mit der ich rechnen könnte.”
– Andy Lester
14. März 2013 um 20:56 Uhr
+1. Stimme Andy zu. @ Ferruccio, Implementierung Detail der Idee des Programmierers ist nicht dasselbe wie die Implementierung des Compilers definiert
– Benutzer
15. Februar 2014 um 23:08 Uhr
Wenn Sie NULL in einem einfachen Code ohne komplexen Header verwenden, finden Sie den Fehler „NULL ist in diesem Bereich nicht definiert“.
– Künstliche Intelligenz
12. November 2017 um 23:07 Uhr
Andreas Stein
Ich benutze immer:
NULL für Zeiger
'\0' für Zeichen
0.0 für Schwimmer und Doppel
wo 0 gut tun würde. Es geht um die Absichtserklärung. Das heißt, ich bin nicht anal darüber.
Ferruccio
Ich habe vor langer Zeit aufgehört, NULL zugunsten von 0 zu verwenden (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 in C- und C++-Code anscheinend überstrapaziert wurde. Es scheint immer dann verwendet zu werden, wenn ein 0-Wert benötigt wird, nicht nur für Zeiger.
Bei neuen Projekten füge ich dies in einen Projektkopf ein:
static const int nullptr = 0;
Wenn jetzt C++0x-kompatible Compiler eintreffen, muss ich nur noch diese Zeile entfernen. Ein netter Vorteil dabei ist, dass Visual Studio nullptr bereits als Schlüsselwort erkennt und entsprechend hervorhebt.
Die Verwendung von NULL wird langfristig portabler sein. ‘nullptr’ wird für einige Plattformen verfügbar sein und für andere nicht. Ihre Lösung hier erfordert, dass Sie den Präprozessor um Ihre Deklaration herum verwenden, um sicherzustellen, dass er nur bei Bedarf vorhanden ist. NULL wird dies automatisch tun.
– Richard Corden
7. Oktober 2008 um 11:28 Uhr
Ich bin nicht einverstanden. Es wird kurzfristig weniger portabel sein, bis die Compiler aufholen. Langfristig wird es genauso portabel und vielleicht etwas besser lesbar sein.
– Ferruccio
7. Oktober 2008 um 14:37 Uhr
Außerdem können Sie für Ihren Nicht-C++0x-Compiler immer #define nullptr NULL verwenden.
– Anteru
12. Dezember 2009 um 13:16 Uhr
I stimme zu NULL überbeansprucht wird, habe ich gesehen, dass es verwendet wird, um auf das Null-Terminatorzeichen in einer Zeichenfolge zu verweisen! Ich glaube aber nicht, dass das einen kompletten Verzicht rechtfertigt.
– Markieren Sie Lösegeld
22. Juli 2020 um 13:59 Uhr
abonniert
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 Zeigern arbeiten.
1) Es erklärt Ihre Absicht (lassen Sie mich nicht Ihren gesamten Code durchsuchen, um herauszufinden, ob eine Variable ein Zeiger oder ein numerischer Typ ist).
2) In bestimmten API-Aufrufen, die variable Argumente erwarten, verwenden sie einen NULL-Zeiger, 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 verlangt der va_arg-Aufruf einen 64-Bit-Zeiger, aber Sie übergeben nur eine 32-Bit-Ganzzahl. Scheint mir, als ob Sie sich darauf verlassen, dass die anderen 32-Bits für Sie auf Null gesetzt werden? Ich habe bestimmte Compiler (zB Intels icpc) gesehen, die nicht so gnädig sind – und das hat zu Laufzeitfehlern geführt.
Die Verwendung von NULL wird langfristig portabler sein. ‘nullptr’ wird für einige Plattformen verfügbar sein und für andere nicht. Ihre Lösung hier erfordert, dass Sie den Präprozessor um Ihre Deklaration herum verwenden, um sicherzustellen, dass er nur bei Bedarf vorhanden ist. NULL wird dies automatisch tun.
– Richard Corden
7. Oktober 2008 um 11:28 Uhr
Ich bin nicht einverstanden. Es wird kurzfristig weniger portabel sein, bis die Compiler aufholen. Langfristig wird es genauso portabel und vielleicht etwas besser lesbar sein.
– Ferruccio
7. Oktober 2008 um 14:37 Uhr
Außerdem können Sie für Ihren Nicht-C++0x-Compiler immer #define nullptr NULL verwenden.
– Anteru
12. Dezember 2009 um 13:16 Uhr
I stimme zu NULL überbeansprucht wird, habe ich gesehen, dass es verwendet wird, um auf das Null-Terminatorzeichen in einer Zeichenfolge zu verweisen! Ich glaube aber nicht, dass das einen kompletten Verzicht rechtfertigt.
– Markieren Sie Lösegeld
22. Juli 2020 um 13:59 Uhr
Wenn ich mich richtig erinnere, ist NULL in den von mir verwendeten Headern anders definiert. Für C ist es als (void*)0 definiert und für C++ ist es nur als 0 definiert. Der Code sah ungefähr so aus:
Persönlich verwende ich immer noch den NULL-Wert, um Nullzeiger darzustellen, es macht deutlich, dass Sie einen Zeiger und keinen ganzzahligen Typ verwenden. Ja, intern ist der NULL-Wert immer noch 0, wird aber nicht als solcher dargestellt.
Außerdem verlasse ich mich nicht auf die automatische Umwandlung von ganzen Zahlen in boolesche Werte, sondern vergleiche sie explizit.
Verwenden Sie zum Beispiel lieber:
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 ist, wo man es einfach verwenden kann nullptr anstatt NULLund auch nullptr_t das ist die art von a nullptr.
9869500cookie-checkVerwenden Sie NULL oder 0 (Null) für Zeiger in C++?yes
Warten Sie, muss ein Nullzeiger nicht als falsch ausgewertet werden, unabhängig davon, ob null intern null ist oder nicht?
– Muhende Ente
23. Mai 2013 um 19:42 Uhr
stackoverflow.com/questions/9894013/… und c-faq.com/null/ptrtest.html bestätigen dies
– Muhende Ente
23. Mai 2013 um 19:46 Uhr