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

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag 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.
Zuletzt geändert von Krishty am 11.10.2009, 00:05, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: 32 und 64 Bits, ints und enums

Beitrag 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?
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: 32 und 64 Bits, ints und enums

Beitrag 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ß :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
klickverbot
Establishment
Beiträge: 191
Registriert: 01.03.2009, 19:22
Echter Name: David N.

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

Beitrag 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…
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag 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 :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
TGGC
Establishment
Beiträge: 569
Registriert: 15.05.2009, 18:14
Benutzertext: Ich _bin_ es.
Alter Benutzername: TGGC
Echter Name: Ich _bin_ es.
Wohnort: Mainz
Kontaktdaten:

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

Beitrag 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...)
Antworten