NULL und 0



  • Original erstellt von groovemaster2002:
    **Welcher *Wert* sich hinter einem Nullzeiger verbirgt ist systemabhängig
    **

    und irrelevant, btw.

    Wenn du alleredings ein Programm auf exotische Hardware portierst (siehe mein vorheriger Poll), musst du deinen gesamten Code umschreiben, falls du 0 verwendest hast, da hier ein Nullzeiger jetzt nicht mehr den Wert 0 hat sondern zB 0xB00000000000.

    Dann würde ich mich schnellstens beim ISO-Komitee beschweren. Die schreiben nämlic in 6.3.2.3p3 (ISO-C) »An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant«. Alles falsch? Krieg' ich dann mein Geld zurück?

    Wenn du NULL verwendet hast ist dies kein Problem, da hier lediglich das define angepasst wird.

    Die Definition von NULL liegt in stdlib.h/cstdlib und auf die hat man keinen Zugriff.

    printf("%p\n", NULL);
    Wieso soll dies ein *absolut falsches Konstrukt* sein?

    Weil zB 'sizeof (int) != sizeof(void*)'. Beim Turbo-C-Compiler hat man je nach Speichermodell NULL auf die passende Größe gesetzt, damit in solchen Situationen (va_args) die Programme nicht abstürzen, obwohl sie falsch sind.

    C beschreibt übrigens keine Computer sondern virtuelle Maschinen. Ein Zeiger in C muss überhaupt nicht auf physikalische Adressen im Speicher zeigen.



  • Original erstellt von groovemaster2002:
    Eben nicht. Welcher *Wert* sich hinter einem Nullzeiger verbirgt ist systemabhängig. Im normalen C/C++ Kontext auf x86 (32/64 Bit) Maschinen mag deine Behauptung zutreffen. Wenn du alleredings ein Programm auf exotische Hardware portierst (siehe mein vorheriger Poll), musst du deinen gesamten Code umschreiben, falls du 0 verwendest hast, da hier ein Nullzeiger jetzt nicht mehr den Wert 0 hat sondern zB 0xB00000000000. Wenn du NULL verwendet hast ist dies kein Problem, da hier lediglich das define angepasst wird. Wie Peter Piksa schon gesagt hat, es ist ein Unterschied ob dann printf "<null>" oder "0xB00000000000" ausgibt.

    darf ich mal den C++ Standard zitieren?

    A null pointer constant is an integral constant expression rvalue of integer type that evaluates to zero.

    Und jetzt erklär mir mal wie 0xB0000 zu 0 werden kann.

    Daniel E. hat recht mit seiner Behauptung - der Standard bestätigt es.

    0 ist im Zeigerkontext etwas anderes als im nicht-Zeiger Kontext. Denn 0 im Zeigerkontext steht für 'NULL-Zeiger'. Ein 'NULL-Zeiger' muss nicht auf die Addresse 0x0000 zeigen (das ist implementation defined).



  • @Daniel E:
    Was hat
    'sizeof (int) != sizeof(void*)'
    mit
    printf("%p\n", NULL);
    zu tun. '%p' zeigt an, dass das Argument ein Zeiger ist und NULL ist nunmal ein Synonym für einen Zeiger, nämlich eine Nullzeiger. Wenn printf nicht weiss wie ein Zeiger aussieht bzw. wie man den aus einer Argumentliste rauskriegt ist das doch nicht die Schuld des Programmierers der printf nutzt. Persönlich halte ich es sogar für unclever, dass Funktionen wie printf va_arg benutzen, da hier Argument an int Grenzen festgesetzt werden.
    Eigentlich dachte ich das *Gurus* soweit denken könnten, dass man auf exotischen Systemen selbstverständlich eine angepasste Version für Funktionen wie printf braucht, nicht umsonst nutzt zB die C stdlib Makros wie _M_ALPHA etc.

    und irrelevant, btw

    OK, ist deine Meinung und die respektier ich *schleim*. Meine Meinung ist das jedenfalls nicht.

    @Shade Of Mine
    wenn du meine Polls mal genau durchgelesen hättest, wäre dir aufgefallen, dass ich nicht behaupte, dass NULL != 0 in Standard C/C++ ist. Oder glaubst du auf exotischer Hardware (naja Windows reicht ja als Bsp. eigentlich auch schon) kommst man mit dem Standard immer ans Ziel?

    0 ist im Zeigerkontext etwas anderes als im nicht-Zeiger Kontext. Denn 0 im Zeigerkontext steht für 'NULL-Zeiger'. Ein 'NULL-Zeiger' muss nicht auf die Addresse 0x0000 zeigen (das ist implementation defined).

    Damit bestätigst du vollkommen meine Ansicht. Die Frage war ja auch ob NULL (bei NULL geh ich jedenfalls davon aus, dass jemand damit einen Nullzeiger beschreibt) und 0 dasselbe sind. Betrachtet man nun 0 im Kontext der Abfrage eines Zeigers sage ich ja, im Kontext des Wertes eines Zeigers nein. Wie ein Nullzeiger ausgewertet wird hängt ja schliesslich vom Compiler ab. Denn auf Maschinensprache-Ebene ist es Wurscht ob du nun einen Zeiger oder Integer hast.

    mov eax, 0x00401000

    Wurde nun hier eax ein Zeiger oder ein Integer zugewiesen?

    Aber ich will nicht zu weit abdriften. Meine damit nur wer 0 verwenden will, bitteschön, der solls auch tun. Dann kann ers bei Abfragen aber auch ganz weglassen.

    if (ptr) ...
    if (!ptr) ...
    

    Ich werde jedenfalls sowohl in C als auch C++ weiterhin NULL verwenden. 😉

    [ Dieser Beitrag wurde am 16.03.2003 um 16:53 Uhr von groovemaster2002 editiert. ]



  • Original erstellt von groovemaster2002:
    Was hat
    'sizeof (int) != sizeof(void
    )'
    mit
    printf("%p\n", NULL);
    zu tun. '%p' zeigt an, dass das Argument ein Zeiger ist
    *

    Aber nicht zur Compilezeit. Nehmen wir mal wieder ein exotisches System, zB ein solches wo Funktionsparameter auf den Stack gelegt werden. Es wird 'etwas' mit sizeof NULL auf den Stack gelegt, und sizeof (void*) gepopt.

    NULL ist nunmal ein Synonym für einen Zeiger, nämlich eine Nullzeiger.

    Nein, das ist der springende Punkt. NULL ist eine Nullzeigerkonstante, bestimmt kein Nullzeiger. Was NULL im nicht-Zeigerkontext macht ist nicht vorgeschrieben.

    Eigentlich dachte ich das *Gurus* soweit denken könnten, dass man auf exotischen Systemen selbstverständlich eine angepasste Version für Funktionen wie printf braucht, nicht umsonst nutzt zB die C stdlib Makros wie _M_ALPHA etc.

    Was willst Du mit deiner 'angepassten Version von printf' machen? Soll sie die Spezifikation von printf erfüllen? Wer ist _M_ALPHA?

    Denn auf Maschinensprache-Ebene ist es Wurscht ob du nun einen Zeiger oder Integer hast.

    Exotische Systeme: Was ist, wenn für Addressoperationen andere Register benutzt werden als für Integer? Was, wenn ein Zeiger größer ist, als ein Integer?
    http://www-info2.informatik.uni-wuerzburg.de/dclc-faq/kap1.html sollte alle Fragen zu Nullzeigern klären.



  • Original erstellt von groovemaster2002:
    **@Shade Of Mine
    wenn du meine Polls mal genau durchgelesen hättest, wäre dir aufgefallen, dass ich nicht behaupte, dass NULL != 0 in Standard C/C++ ist. Oder glaubst du auf exotischer Hardware (naja Windows reicht ja als Bsp. eigentlich auch schon) kommst man mit dem Standard immer ans Ziel?
    **

    Ja das glaube ich. Nicht umsonst hat Standard C++ große einbußen um auch auf exotischer hardware zu rennen (zB threads, gui, sokcets,...)

    Ich hab leider den Standard von eC++ nicht, aber ich denke auch dort gilt in bezug auf 0-zeiger das gleiche.

    Zumindest auf mikrokontrollern ist es so (OK, da verwendet mein Vater C, aber dennoch: 0 bleibt immer 0)

    Damit bestätigst du vollkommen meine Ansicht. Die Frage war ja auch ob NULL (bei NULL geh ich jedenfalls davon aus, dass jemand damit einen Nullzeiger beschreibt) und 0 dasselbe sind. Betrachtet man nun 0 im Kontext der Abfrage eines Zeigers sage ich ja, im Kontext des Wertes eines Zeigers nein. Wie ein Nullzeiger ausgewertet wird hängt ja schliesslich vom Compiler ab. Denn auf Maschinensprache-Ebene ist es Wurscht ob du nun einen Zeiger oder Integer hast.

    mov eax, 0x00401000
    

    Wurde nun hier eax ein Zeiger oder ein Integer zugewiesen?
    auf exotischer hardware kann ein zeiger größer oder kleiner als ein int sein.
    die maschinen ebene ist aber egal für c/c++ programmierer.

    ob er aus einem
    int* p=0;
    ein
    mov xxx, 0x0000
    oder
    mov xxx, 0xgeileaddy
    macht ist mir doch egal.
    auch wenn p nun nicht auf die adresse 0 zeigt, dann ist p dennoch ein 0-zeiger.
    [quote]
    Aber ich will nicht zu weit abdriften. Meine damit nur wer 0 verwenden will, bitteschön, der solls auch tun. Dann kann ers bei Abfragen aber auch ganz weglassen.

    if (ptr) ...
    if (!ptr) ...
    

    Ich werde jedenfalls sowohl in C als auch C++ weiterhin NULL verwenden. 😉

    verwende NULL - niemand will es dir ausreden.
    aber merke:
    NULL liefert immer 0, 0L, 0LL oder ähnliches (immer 0)

    lies den standard wenn du uns nicht glaubst.



  • @Daniel E.
    Wer sizeof(NULL) als printf Argument und im Formatstring "%p" benutzt der ist irgendwie selbst dran Schuld. 😉
    Mit angepasster Version meine ich natürlich, dass man den Source von printf braucht und das ganze nochmal neu compilieren muss für das entsprechende System.

    @Shade Of Mine:

    ob er aus einem
    int* p=0;
    ein
    mov xxx, 0x0000
    oder
    mov xxx, 0xgeileaddy
    macht ist mir doch egal.

    (Wusste garnicht dass es g, i, l und y im Hex-Format gibt. 😃 0xdeadbeef)
    Mag dir zwar egal sein, aber nicht Leuten (wie mir), die teilweise Sequenzen in Assembler programmieren (weiss leider net ob Inline Assembler im C++ Standard erlaubt ist). Da ich mir der Problematik bewusst bin, bin deshalb u.a. gerade dabei sämtliche Routinen direkt in Assembler Module zu packen. Obs was bringt weiss ich nicht, da für andere Systeme solche Sachen meist eh neu programmiert werden müssen. Aber allein um C/C++ strikter von Assembler abzugrenzen denke ich ist dies sinnvoller. Weiss allerdings noch nicht was ich mit inline inline Assembler Funktionen 🙂 machen soll.
    also

    inline int TuIrgendwas()
    {
      __asm {
         ...
      }
    }
    


  • Original erstellt von groovemaster2002:
    **Mit angepasster Version meine ich natürlich, dass man den Source von printf braucht und das ganze nochmal neu compilieren muss für das entsprechende System.
    **

    printf wird wohl überall mehr oder weniger gleich aussehen - vorallem das verhalten ist identisch.

    sicher braucht man für jedes system ein eigenes printf - aber das ist ja der sinn einer library wie die C/C++ Runtime Library: der programmierer muss sich nicht darum kümmern.

    Mag dir zwar egal sein, aber nicht Leuten (wie mir), die teilweise Sequenzen in Assembler programmieren (weiss leider net ob Inline Assembler im C++ Standard erlaubt ist). Da ich mir der Problematik bewusst bin, bin deshalb u.a. gerade dabei sämtliche Routinen direkt in Assembler Module zu packen. Obs was bringt weiss ich nicht, da für andere Systeme solche Sachen meist eh neu programmiert werden müssen.

    damit begibst du dich sowieso in eine compiler und OS abhängigkeit -> insofern hat das nix im C++ Forum zu suchen.

    In C++ braucht man sich nicht um sowas kümmern - und wenn man es doch mal muss, dann ist das sowieso system-spezifisch.



  • Dazu muss man jedoch auch sagen, dass NULL bei Datenbanken nicht das selbe sind wie in C oder C++. Allein schon in den beiden Sprachen gibt es Unterschiede, da das eine nur ein Integer ist und das andere ein richtiger Zeiger auf 0. Wie das jetzt jedoch in Delphi, Java und C# ist weiß ich nicht. Aber in PHP ist null ein Witz der nichts zu sagen hat.

    Meine Erfahrung jedenfalls.



  • @geeky@work
    Musst du wirklich Einträge die sehr alt sind neu aufleben lassen (der letzte Eintrag vor deinem ist von 2003!)?



  • @geeky:
    Aus Versehen auf Seite 53 geklickt und es noch nicht gemerkt?
    Komm mal zurück ins hier und jetzt 😃



  • Ach wie schön, die alte NULL/0 Diskussion wieder 🙂
    Wäre ja auch fad so ein Jahr ohne NULL/0 Diskussion.

    Die einzig IMO vernünftige Antwort ist: in C++ gibt es kein NULL sondern nur 0.
    Wer ein blödes Makro verwenden will soll sich bitte mit PROJEKTNAME_NULLPTR oder ähnlichem selbst eines definieren.



  • geeky wenn du deinen Spamcounter hochtreiben willst, indem du bei toten Threads den Nonsense-Defibrilator ansetzt, solltest du dich vorher einloggen sonst bringt des nix.


Anmelden zum Antworten