Seite 1 von 1

(gelöst) 32 und 64 Bits, ints und enums

Verfasst: 10.10.2009, 22:25
von Krishty
Hi,

Ich stehe gerade auf dem Schlauch. Ich konvertiere eine 32-Bit-Ganzzahl zu einer 64-Bit-Ganzzahl und umgekehrt. Die oberen 32 Bits sind mir dabei wumpe. Der Clou ist, dass die Zahl bei der Konvertierung zu 32 Bits durch XOR „gesalzen“ und bei der Rückkonvertierung zu 64 Bits wieder „entsalzt“ wird – und der Wert, mit dem das geschieht, ist ein enum. Und das ist dann auch der Punkt, an dem ich irgendwie die Orientierung verliere …:

Code: Alles auswählen

enum { Salt = 0xEF56F3C9 };

unsigned long _64to32(unsigned long long p_) {
    return static_cast<unsigned long>(p_ ^ Salt);
}

unsigned long long _32to64(unsigned long p_) {
    return static_cast<unsigned long long>(p_) ^ static_cast<unsigned long long>(Salt);
}
Dieser Code kracht, und das nicht erst bei der Ausführung:

Code: Alles auswählen

(_64to32) warning C4310: cast truncates constant value
(_32to64) warning C4309: 'static_cast' : truncation of constant value
Nun verstehe ich nicht: Warum wird 0xEF56F3C9 beim Cast zu unsigned long abgeschnitten? Und warum sogar beim Cast zu unsigned long long?!? Salt kann doch unmöglich eine signed long sein, dann hätte sich der Compiler schon bei der Initialisierung mit Constant-out-of-Range beschwert…?

Gruß, Ky

P.S.: Das Ganze spielt sich in VS 2008 im x64-Modus ab.

Re: 32 und 64 Bits, ints und enums

Verfasst: 10.10.2009, 23:39
von Jörg
Die 2010 beta meckert nicht.
Was passiert, wenn du bei 32to64 die casts weglaesst?
Mal den Assembler-Code geprueft, was da raus kommt?

Re: 32 und 64 Bits, ints und enums

Verfasst: 10.10.2009, 23:56
von Krishty
Jörg hat geschrieben:Was passiert, wenn du bei 32to64 die casts weglaesst?

Code: Alles auswählen

warning C4310: cast truncates constant value
Jörg hat geschrieben:Mal den Assembler-Code geprueft, was da raus kommt?
Ohne Casts:

Code: Alles auswählen

64to32:
mov         rax,qword ptr [p_]
xor         rax,0FFFFFFFFEF56F3C9h
ret

32to64:
mov         eax,dword ptr [p_] 
xor         eax,0EF56F3C9h 
mov         eax,eax 
ret
Mit Casts:

Code: Alles auswählen

64to32:
mov         rax,qword ptr [p_] 
xor         rax,0FFFFFFFFEF56F3C9h 
ret

32to64:
mov         eax,dword ptr [p_Identity] 
xor         rax,0FFFFFFFFEF56F3C9h 
ret
Er interpretiert das enum also tatsächlich signed. F**k. Das regt mich gerade tierisch auf … enums sollen sauberer als #defines sein, aber dafür passiert dann sowas. Ich mache Salt mal zu einer static const unsigned long und checke, ob er das schluckt …

Edit: Klappt, gibt auch keine Compiler-Warnungen mehr. Danke für den Denkanstoß :)

Re: (gelöst) 32 und 64 Bits, ints und enums

Verfasst: 11.10.2009, 01:19
von klickverbot
OT: Was ist eigentlich die Motivation dahinter, enums nicht als Aufzählung, sondern mit einem Element als #define- bzw. const-Ersatz zu verwenden? Sieht man ja doch ab und zu…

Re: (gelöst) 32 und 64 Bits, ints und enums

Verfasst: 11.10.2009, 01:35
von Krishty
Die Vorteile gegenüber #define sollten klar sein – man verpestet das globale Namespace nicht mehr, die Werte sind typsicher (naja), man kann sie sich im Debugger anzeigen lassen, etc.

Gegenüber static const wird es schwieriger. Wenn ich mich recht erinnere, produziert enum ausschließlich rvalues, was bedeutet, dass der Compiler kein Symbol im Datenbereich anlegen muss (ein enum-Wert hat schließlich keine Adresse). static-const-deklarierte Symbole hingegen haben eine Adresse, gegen die gelinkt werden muss, und müssen initialisiert werden (auch, wenn Compiler da sehr gut optimieren können).

Natürlich alles unter Vorbehalt :)

Re: (gelöst) 32 und 64 Bits, ints und enums

Verfasst: 24.10.2009, 09:47
von TGGC
Du benutzt enums falsch. Den salt solltest du als static const definieren, dann kannst du auch den Typ angeben. Aber wenn du den enum Typ wegcastest und einfach einen beliebigen eigenen dafuer einsetzt, dann ist es kein Wunder wenn es ja nach Compiler fehlschlaegt. Kann ja keiner vorher hellsehen, was du mit dem enum machen wirst. f'`8k

[ ] Autocogito


Gruß, TGGC (Was Gamestar sagt...)