Pointer != NULL : C ? C++
-
Ist das C Style
if(pointer != NULL)...
Und das C++ Style
if(pointer)...
Oder ist das egal?
-
1. Das zweite Beispiel ist C Style
2. Ja, das ist C++ Style
3. Alles ist höchst subjektiv und daher sind Aussagen 1 und 2 nicht allgemeingültig
-
Wenn beide pointer raw pointers sind, dann ist beides C Stil. In C++ verlässt man sich auf RAII und smart pointers.
mfg, NRWsoft
-
NULL ist C-Style. In C++ verwendet man 0, bzw nullptr in C++0x, wobei ich das != 0/nullptr ganz weglassen würde.
-
314159265358979 schrieb:
NULL ist C-Style. In C++ verwendet man 0
In C++ ist NULL als 0 definiert.
-
ääähhh schrieb:
In C++ ist NULL als 0 definiert.
Eben.
-
Ein NULL in C ist als "(void *)0" definiert. Wird ein C Include korrekt (ein Systeminclude wie "stdio.h") in eine C++ Datei inkludiert, wird NULL als "0L" redefinert.
Im Prinzip läuft es auf des gleiche hinaus, da im Memoryrange an der Adresse 0 immer der Inhalt 0 steht. Das ist eine Hardwaredefinition auf x86/x86_64 Systemen und wird auf nicht-Intelsystemen im Betriebssystemkern erzwungen.
Ein "if (pointer)" funktioniert in C und C++ gleichermaßen. Es wird in beiden Fällen in ein Test auf 0 reduziert, kann man im Assembleroutput auch prima sehen. Ich demonstriere es einfach mal.
test1.c wurde mit "gcc -O0 -S test1.c" und test2.cpp wurde mit "g++ -O0 -S test2.cpp" übersetzet. Man muss hier die Optimierung abschalten, weil er sonst wegen der Konstante "bla" das if herausoptimiert.
test1.c
#include <stdio.h> int main() { char *bla = NULL; if (bla) printf("non null\n"); return 0; }
test1.s ... nur das main() label
main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 subq $16, %rsp movq $0, -8(%rbp) cmpq $0, -8(%rbp) je .L2 movl $.LC0, %edi call puts
test2.cpp
#include <iostream> #include <cstdio> // to get NULL int main() { char *bla = NULL; if (bla) std::cout << "non null" << std::endl; return 0; }
test2.s ... nur das mein() label
main: .LFB963: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 subq $16, %rsp movq $0, -8(%rbp) cmpq $0, -8(%rbp) je .L2 movl $.LC0, %esi movl $_ZSt4cout, %edi call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, %esi movq %rax, %rdi call _ZNSolsEPFRSoS_E
Es geht hier in beiden Assemblerquelltexten um die Zeile 11, also das "cmp". Es ist selbst unoptimiert vollkommen identisch. (um fragen vorzubeugen, ja es ist 64 Bit Code)
-
Akiko schrieb:
Ein NULL in C ist als "(void *)0" definiert.
Ich bin mir sehr sicher, dass dies in C (eventuell nur C89?) nicht so festgelegt ist, aber ich bin gerade zu faul, den Standard zu durchsuchen. In C++ ist hingegen festgelegt, dass NULL tatsächlich 0 sein muss, weswegen man auch 0 schreiben kann, wenn man NULL meint.
Der Rest deines Beitrags ist "Beweis" durch Beispiel mit deinem einen Compiler.
-
SeppJ schrieb:
Der Rest deines Beitrags ist "Beweis" durch Beispiel mit deinem einen Compiler.
Da haste allerdings recht. Dann korrigiere ich es mal lieber zu einem "es gilt für Unix-artige Systeme mit clang, gcc, Intel und DEC-Conmpiler unter Verwendung der glibc ab 2.3 und der stdc++ v3 und v4".
-
Warum haben sie's eigentlich NULL und nicht ZERO genannt?!
-
Um von "zero" zu unterscheiden. Zero bezeichnet die Zahl 0, null heißt so viel wie "nichtig" oder "nicht-existent".
-
Vielleicht haben sie sich auch von Lisp inspirieren lassen ... null? bzw. die leere Liste '(). Alternative in anderen Sprachen ist nil.
-
314159265358979 schrieb:
NULL ist C-Style. In C++ verwendet man 0, bzw nullptr in C++0x, wobei ich das != 0/nullptr ganz weglassen würde.
Ich verwende in C++
NULL
(oder das selbstgebasteltenullptr
-Template). Der Code ist klarer als mit0
, zudem kann man später leichter durch den sicheren C++0x-nullptr
ersetzen.
-
Ich habe gerade noch mal im Standard gestöbert: NULL ist in C++ garantiert 0 (4.10), in C ist es implementation defined (7.17). Das ändert aber auch nichts an den Antworten in diesem Thread, es dient nur als Bestätigung. Man muss aber vermutlich sehr lange suchen, um eine C-Implementierung mit NULL!=0 zu finden .
-
ääähhh schrieb:
314159265358979 schrieb:
NULL ist C-Style. In C++ verwendet man 0
In C++ ist NULL als 0 definiert.
Was nichts an der Tatsache ändert, dass es unleserlich ist und deshalb nicht verwendet werden sollte.
-
314159265358979 schrieb:
ääähhh schrieb:
In C++ ist NULL als 0 definiert.
Was nichts an der Tatsache ändert, dass es unleserlich ist und deshalb nicht verwendet werden sollte.
Warum genau ist
NULL
zur Kennzeichnung von Zeigern unleserlicher als das Integer-Literal0
?
-
Nexus schrieb:
Warum genau ist
NULL
zur Kennzeichnung von Zeigern unleserlicher als das Integer-Literal0
?Ich benutze ausschließlich NULL bei Pointern und finde es wesentlich leserlicher, denn NULL signalisiert sofort, dass die Variable ein Pointer ist und es signalisiert sofort, dass der Pointer zum Nullzeiger wird.
Andererseits ist in der Regel manuelle Ressourcenverwaltung sowieso bei mir ausgeschlossen, daher gibt es auch praktisch keine NULLs mehr.
mfg, NRWsoft
-
In C ist NULL üblicherweise als ((void*) 0) o. vglb. definiert. In C++ ist diese Definition explizit ausgeschlossen (18.1 (4), Fußnote 180), weil das strengere Typsystem in C++ damit Dinge wie
non_pod *ptr = NULL;
nicht hergäbe. Explizit vorgeschlagen werden 0 und 0L als Alternativen, und meistens wird auch eine dieser beiden Varianten benutzt. Das Problem, dass sich daraus ergibt (und der Grund, warum NULL in C++ unpopulär ist, obwohl es eigentlich ziemlich gleichgültig ist, ob man NULL oder 0 schreibt), ist, dass NULL verwirrenderweise zwar eine "pointer constant", aber selbst kein Zeiger ist. Zum Beispiel wird
#include <cstddef> #include <iostream> template<typename T> struct is_pointer_mp { static bool const val = false; }; template<typename T> struct is_pointer_mp<T*> { static bool const val = true ; }; template<typename T> bool is_pointer(T) { return is_pointer_mp<T>::val; } int main() { std::cout << (is_pointer(NULL) ? "wahr" : "falsch") << std::endl; }
"falsch" ausgeben. Gcc 4.5 warnt hier übrigens:
test.cc: In Funktion »int main()«: test.cc:10:32: Warnung: Übergabe von NULL an Nicht-Zeiger-Argument 1 von »bool is_pointer(T) [with T = long int]«
Schlussendlich kann man es so oder so machen; es ist Geschmackssache. Ein Unterschied in der Programmlogik ergibt sich daraus jedenfalls nicht.
-
Ja, man muss sich bewusst sein, dass
NULL
einint
und somit nicht typsicher ist. Typsicherheit erreicht man mit dieser Klasse, die aber wieder andere Probleme hat (v.a. im Bezug auf Memberfunktionszeiger).In C++0x wird die Problematik mit
nullptr
ja sauber gelöst.
-
seldon schrieb:
In C ist NULL üblicherweise als ((void*) 0) o. vglb. definiert. In C++ ist diese Definition explizit ausgeschlossen (18.1 (4), Fußnote 180), weil das strengere Typsystem in C++ damit Dinge wie
non_pod *ptr = NULL;
nicht hergäbe. Explizit vorgeschlagen werden 0 und 0L als Alternativen, und meistens wird auch eine dieser beiden Varianten benutzt. Das Problem, dass sich daraus ergibt (und der Grund, warum NULL in C++ unpopulär ist, obwohl es eigentlich ziemlich gleichgültig ist, ob man NULL oder 0 schreibt), ist, dass NULL verwirrenderweise zwar eine "pointer constant", aber selbst kein Zeiger ist. Zum Beispiel wird
#include <cstddef> #include <iostream> template<typename T> struct is_pointer_mp { static bool const val = false; }; template<typename T> struct is_pointer_mp<T*> { static bool const val = true ; }; template<typename T> bool is_pointer(T) { return is_pointer_mp<T>::val; } int main() { std::cout << (is_pointer(NULL) ? "wahr" : "falsch") << std::endl; }
"falsch" ausgeben.
Aber 0 bringt da auch nix.