Konvertierung Frage



  • Geht das hier?

    unsigned __int32 BytesToInt32(const unsigned char* B) {
    		return *(unsigned __int32*)(B);
    	}
    

    wird hier der Wert nochmal kopiert und zurückgegeben?
    hab es jetzt mit einem c-casts gemacht, weil ich mit reinterpret_cast das Const nicht wegbekomme.



  • KnobelDran schrieb:

    Geht das hier?

    unsigned __int32 BytesToInt32(const unsigned char* B) {
    		return *(unsigned __int32*)(B);
    	}
    

    Formal ist das undefiniertes Verhalten(C++11 3.10/10).
    Schau in's Handbuch Deines Compilers, ob das definiert ist. Stichwort ist "Aliasing" oder ganz allgemein "Lvalues", bzw. "Glvalues".

    Und wenn Du schon in's Handbuch schaust, guck gleich nach, ob es nicht einen ordentlichen Datentyp statt dieses häßlichen __int32 gibt. 😉

    Viel Erfolg,
    FW



  • KnobelDran schrieb:

    Wie meinst du das mit dem reinterpret_cast?

    so?

    unsigned __int32 BytesToInt32(unsigned char* B) {
    		unsigned __int32 retVal;
    		retVal = *reinterpret_cast<unsigned __int32*>(B);
    		return retVal;
    	}
    

    Ja, sieht doch mehr oder weniger schick aus.

    reinterpret_cast ist fast immer die Bankrotterklärung des Software-Designs, aber hier ist es eben schnell wie Schmitz Katze. Da darf man sich durchaus fragen lassen, ob man dafür nicht einen Zensurbalken über eine solche Funktion legen sollte und das akzeptiert. Und damit klar ist, dass hier schwarze Magie passiert, schreibst Du es ja auch in den Quellcode: "reinterpret_cast".

    KnobelDran schrieb:

    Geht das hier?

    unsigned __int32 BytesToInt32(const unsigned char* B) {
    		return *(unsigned __int32*)(B);
    	}
    

    wird hier der Wert nochmal kopiert und zurückgegeben?
    hab es jetzt mit einem c-casts gemacht, weil ich mit reinterpret_cast das Const nicht wegbekomme.

    Du kopierst, da spielt es keine Rolle, ob Du ein int const oder ein int liest. NEVER EVER solltest Du C-Casts verwenden. Man beachte, dass ich Dir zum Casten rate - was schon leicht grenzwertig ist, aber C-Casts gehen ohne guten Grund ÜBERHAUPT NICHT. In C++ gibt es keine guten Gründe mehr.

    unsigned __int32 BytesToInt32(const unsigned char* B) {
    		return *reinterpret_cast< unsigned __int32 const *>(B);
    	}
    

    Ansonsten könntest Du noch Unions verwenden.

    union IntConverter
    {
      char          charArray[4]
      unsigned int  intValue;
    };
    
    union IntConverter ic;
    
    ic.charArray[0] = '1';
    ic.charArray[1] = '2';
    ic.charArray[2] = '3';
    ic.charArray[3] = '4';
    
    printf( "intValue: %d\n", ic.intValue );
    

    Schön ist was anderes, aber da ist eher die Frage, wieso Du char-Arrays nach int umwandelst. Und wenn die Aufgabe unschön ist, dann wird da auch keine schöner Quellcode draus.

    Das Union bietet sich zum Beispiel an, wenn Du 4 Byte aus einer Datei einlädst und dafür einen char-Pointer brauchst, diese vier Byte aber in wirklichkeit eben ein int sind.



  • Hallo Xin,

    laut C++ Standard aber undefiniertes Verhalten - es darf nur aus dem Union-Member gelesen werden, in dem zuletzt reingeschrieben wurde (auch wenn dieser Union-Cast überaus beliebt ist)!



  • Th69 schrieb:

    Hallo Xin,

    laut C++ Standard aber undefiniertes Verhalten - es darf nur aus dem Union-Member gelesen werden, in dem zuletzt reingeschrieben wurde (auch wenn dieser Union-Cast überaus beliebt ist)!

    Natürlich ist das Verhalten in C++ undefiniert, schon alleine weil das Integer von einer Motorola CPU anders geschrieben wird als von einem Intel oder es CPUs gibt, für die C-Compiler existieren, die aber eine Bytegröße von über 32 Bit haben, ergo ein int auch größer als 32 Bit ist.

    Wie der Fragesteller schon sagte: Windows kompatibel und er möchte nicht auf 5% Sonderfälle eingehen. Dafür ist diese Lösung tragbar.



  • Xin schrieb:

    Das Union bietet sich zum Beispiel an, wenn Du 4 Byte aus einer Datei einlädst und dafür einen char-Pointer brauchst, diese vier Byte aber in wirklichkeit eben ein int sind.

    Genau das mache ich auch, ich habe eine Binärdatei vorliegen und weis das gewisse 4 Bytes eben ein unsigned int sind. Ich denke ich werde die reinterpret_cast<..>(..) Lösung nehmem, das mit dem union ist mir irgendwie suspekt. Vielen Dank!



  • KnobelDran schrieb:

    Ich denke ich werde die reinterpret_cast<..>(..) Lösung nehmem, das mit dem union ist mir irgendwie suspekt.

    Sehe ich auch als die bessere Variante an (wenns denn not tut das so zu machen). UB bzw. Plattformspezifisch ist beides, allerdings sieht man beim reinterpret_cast sofort, dass da was ungewöhnliches passiert. Den wechselnden Zugriff auf verschiedene union-Elemente kann man schnell mal übersehen.



  • KnobelDran schrieb:

    Xin schrieb:

    Das Union bietet sich zum Beispiel an, wenn Du 4 Byte aus einer Datei einlädst und dafür einen char-Pointer brauchst, diese vier Byte aber in wirklichkeit eben ein int sind.

    Genau das mache ich auch, ich habe eine Binärdatei vorliegen und weis das gewisse 4 Bytes eben ein unsigned int sind. Ich denke ich werde die reinterpret_cast<..>(..) Lösung nehmem, das mit dem union ist mir irgendwie suspekt. Vielen Dank!

    Ich nehme diese Lösung in der Regel auch, bzw. ich habe eine Endian-Class, die sich in Abhängigkeit des Prozessortyps initialisiert. Der gebe ich mit, was ich für Daten lese (char/short/int...) und welche Endianess ich erwarte. Anschließend frage ich nur noch den Wert ab.
    Der Umgang ist also ähnlich mit dem Union.

    Ein reinterpret_cast<> sollte Dir aber auch sehr suspekt sein.
    Du solltest also eventuell in einem Kommentar dokumentieren, was das soll, denn ein reinterpret_cast<> ist ein klarer Hinweis auf ein Problem, eine offenliegende Wunde in der Architektur. Der Kommentar wirkt da als Pflaster. 😉



  • Warum liest dunicht direkt in den int ein, ala:

    int i;
    lies_nach(&i, sizeof i);
    


  • Könnte ich, wenn du mir sagst welchen Vorteil das gegenüber der Funktion mit return hat und ich den Vorteil als solchen anerkenne :p .

    Bei der Funktion hab ich die Möglichkeit den Wert sofort weiterzuverarbeiten.
    z.B.

    std::cout<<BytesToInt32(someChars);
    


  • Einige Compiler bieten aber Unions als "Workaround" gegen die Strict-Aliasing rule an. (z.B. GCC gcc.gnu.org/bugs/#known )


  • Mod

    Also

    uint32_t BytesToInt32(const uint8_t* B) {
        return B[0]+(B[1]<<0x8)+(B[2]<<0x10)+(B[3]<<0x18);
    }
    

    macht bereits das Richtige? Wieso werden dann memcpy oder absurde Casts überhaupt in Erwägung gezogen?



  • camper schrieb:

    Also

    uint32_t BytesToInt32(const uint8_t* B) {
        return B[0]       // zugriff
                +         // addition
                  (B[1]   // addition und zugriff
                    <<    // shiften
                   0x8)   
                +         // addition
                 (B[2]    // addition und zugriff
                    <<    // shiften
                  0x10)
                +         // addition
                 (B[3]    // addition und zugriff
                   <<     // shift
                  0x18);
    }
    

    macht bereits das Richtige? Wieso werden dann memcpy oder absurde Casts überhaupt in Erwägung gezogen?

    return *                          // Zugriff
             (unsigned __int32*)(B);
    

  • Mod

    Xin schrieb:

    camper schrieb:

    Also

    uint32_t BytesToInt32(const uint8_t* B) {
        return B[0]       // zugriff
                +         // addition
                  (B[1]   // addition und zugriff
                    <<    // shiften
                   0x8)   
                +         // addition
                 (B[2]    // addition und zugriff
                    <<    // shiften
                  0x10)
                +         // addition
                 (B[3]    // addition und zugriff
                   <<     // shift
                  0x18);
    }
    

    macht bereits das Richtige? Wieso werden dann memcpy oder absurde Casts überhaupt in Erwägung gezogen?

    return *                          // Zugriff
             (unsigned __int32*)(B);
    

    Ja, ich habe mir schon gedacht, dass es etwas mit Voodoo zu tun haben muss...


Anmelden zum Antworten