Verbleibende bits eines std::uint64_t werden auf ff gesetzt



  • Ich kann es nicht besser beschrieben, hier der Code (Win7 Visual Studio 2012):

    std::uint8_t da[] = {0xf9, 0xff, 0xff, 0xff};
    
    		std::uint64_t v = 0;
    		for(int b=0; b<4; ++b) {
    			v |= da[b] << (b*8);
    		}
    

    0x9f ist das niederwertigste Byte.
    Mein Debugger sagt:

    0x00000000000000f9
    0x000000000000fff9
    0x0000000000fffff9
    0xfffffffffffffff9
    

    Waruuuuum warum passiert das ich werde wahnsinnig 😕 Wieso steht da am Ende nicht

    0x00000000fffffff9

    in v?



  • Beim letzten "da[b] << (b*8);" hast du (int)0x00000000fffffff9, was eine negative Zahl ist. Beim impliziten Cast in 64-Bit wird das Vorzeichen übernommen, deshalb das seltsame Resultat.

    v |= static_cast<std::::uint64>(da[b]) << (b*8);
    

    sollte das Problem beheben.



  • v |= static_caststd::uint64\_t(da[b]) << (b*8);



  • So einfach und doch so nervig... danke sehr 👍



  • Und damit auch klar ist warum das hier passiert...

    Bevor C++ mit Zahlen rechnet, tut es sie erstmal "promoten".
    Dabei wird aus allem was kleiner ist als ein int ein int (signed!). Auch wenn das kleinere Etwas unsigned war.

    Nennt sich "integral promotion".

    http://en.cppreference.com/w/cpp/language/implicit_cast schrieb:

    Prvalues of small integral types (such as char ) may be converted to prvalues of larger integral types (such as int ).
    In particular, arithmetic operators do not accept types smaller than int as arguments, and integral
    promotions are automatically applied.
    This conversion always preserves the value.
    ...

    (Da stehen dann auch die genauen Regeln wie "promoted" wird.)

    Beispiel:
    http://ideone.com/wEVZ7t


Anmelden zum Antworten