Ausgabe von char *name über cout ?



  • Hallo liebe C++ Gemeinde ..

    Ich kann die folgende Ausgabe nicht wirklich deuten .
    Warum werden diese Zahlen ausgegeben und was repräsentieren sie?

    Folgender Code :

    #include <iostream>
    using namespace std;
    
    int main (int argc, char * const argv[]) {
    
    	char * name;
    	char *aname = "bastard";
    	cout << name << endl;
    	cout << aname << endl;
    
        return 0;
    }
    

    Ausgabe :

    \316\372\355\376 // diese Zahlen ?
    bastard
    

    Mir ist aufgefallen dass die Zahlen nach dem 2ten oder 3ten kompilieren immernoch die selben sind .
    Ich dachte es würde zur Ausgabe einer einzigen Adresse kommen die in "name" gespeichert ist.Dem ist aber nicht so . Warum ?
    aname enthällt ja normalerweise auch nur eine Adresse , woher weiß mein programm also dass es bei

    "cout << aname;// (aname vom typ char*)"
    

    alle Zeichen bis/0 auszugeben hat. Ist dies im Operator << implementiert?
    Und wie kann ich zur Not die Adresse ausgeben die in aname gespeichert ist?

    Mit freundlichen Grüßen .



  • Der Ofstream hat halt für char* die operator<<-Überladung, welche einen C-String auszugeben versucht. Da dein Zeiger aber auf keinen wohlgeformten, nullterminierten C-String zeigt, wird halt irgendein wirres Zeug ausgegeben, was in irgendeinem zufälligen Speicherbereich, auf den der Zeiger zufällig zeigt, steht.

    Edit: Um die Adresse auszugeben, könntest du beispielweise per reinterpret_cast<void*> oder static_cast<void*> oder soetwas Abhilfe schaffen!



  • Ok danke , und wie würde ich jetzt an die Ausgabe der Adresse kommen ?
    Mit einem int cast vieleicht ?



  • std::cout << reinterpret_cast<void*>(name);
    


  • Gewöhn Dir am besten an std::string zu verwenden.
    Char Arrays sind zwar nett, bergen aber viele Gefahren. Über den []-operator kann man bei einem std::string auch auf die einzelnen Zeichen zugreifen.



  • Decimad schrieb:

    std::cout << reinterpret_cast<void*>(name);
    

    Ein static_cast reicht völlig 😉



  • Und ich hab andersherum gedacht: Ein reinterpret_cast reicht völlig!



  • Warum die Brechstange nehmen, wenn der Schraubenzieher reicht?



  • reinterpret_cast behandelt das Objekt sozusagen nur, als wäre es von einem anderen Typ, static_cast enthält auch Konvertierungslogik. Von daher erschließt sich mir der Vergleich mit der Brechstange nicht so ganz.



  • reinterpret_cast kann alles Casten. static_cast nur, wo es Sinn macht.



  • Naja, wir würden da jetzt wohl ewig drüber streiten...



  • Ein reinterpret_cast kann z.B. auch einen int in einen Zeiger casten. Oder zwischen Zeigern casten, die gar nichts miteinander zu tun haben ( double** zu MyClass* ). Das ist in den meisten Fällen ein Fehler (z.B. Schreibfehler) und in noch mehr Fällen schlechter Stil/Designfehler. Mit static_cast hätte es nicht kompiliert. Deshalb sollte man reinterpret_cast nur benutzen, wenn man sich sicher ist, dass man genau den auch braucht. Natürlich ist static_cast nicht langsamer als reinterpret_cast , die Konvertierungslogik wird nur dann angewendet, wenn es Sinn ergibt (z.B. int zu float ), bei Pointern, wo in den meisten Fällen sich das Bitmuster nicht ändert, wird auch nichts gemacht. Übrigens kann auch reinterpret_cast z.B. bei Pointerkonvertierungen Veränderungen vornehmen, also die Bitmuster von Original und Konvertat müssen nicht übereinstimmen (genauer gesagt ist das Verhalten sogar implemention-defined).



  • Decimad schrieb:

    Naja, wir würden da jetzt wohl ewig drüber streiten...

    Ich hoffe mal nicht. Weil das keine Philosophische Sache ist, sondern Grundwissen 😕



  • Ihr legt mir hier alle irgendwie totales Unwissen in den Mund, weil ich der Meinung bin, ein reinterpret_cast um einen char* kurz als void* zu behandeln ist ein legitimes Vorgehen.
    Ich werde dieses Sprachelement einfach nie wieder erwähnen hier! Vielleicht könnt ihr das ja auch verpixeln, damit bloß niemand die Buchstabenkombination lesen kann 😉



  • Decimad schrieb:

    Ihr legt mir hier alle irgendwie totales Unwissen in den Mund, weil ich der Meinung bin, ein reinterpret_cast um einen char* kurz als void* zu behandeln ist ein legitimes Vorgehen.

    Es ist falsch. static_cast ist die korrekte Vorgehensweise. Da gibt es einfach nichts zu diskutieren.

    Du verwendest ja auch keinen reintrepret_cast um von double nach float zu kommen, oder?



  • Nein! Dort will ich ja die mächtigkeit von static_cast auch ausnutzen!



  • Es ist falsch. static_cast ist die korrekte Vorgehensweise. Da gibt es einfach nichts zu diskutieren.



  • Ich sehe halt den Fehler nicht, darum lasse ich es hier auf den Streit jetzt ankommen. 😉 Was ist daran falsch? Dass man auch static_cast hätte hernehmen können macht den Umstand, dass reinterpret_cast verwendet wurde zu einem Fehler? Ist finde ich keine gute Begründung 😉



  • Decimad schrieb:

    Dass man auch static_cast hätte hernehmen können macht den Umstand, dass reinterpret_cast verwendet wurde zu einem Fehler?

    Ja.
    Wenn Du aber sagst, daß es nicht im naturwissenschaftlichen Sinne falsch ist, weil der Compiler es ja frißt, hast Du natürlich recht. Genau genommen ist es nur ein Verbrechen.



  • Dass der Compiler es frisst, muss ja noch lange nicht bedeuten, dass es auch das tut, was ich will, daher werde ich das nicht als Grund anführen! Aber wenn du mir jetzt zeigen kannst, dass es nicht das tut, was will, werde ich eure etwas forschen "Angriffe" so hinnehmen!


Log in to reply