64 bit Windows - Teil 7
Auweia - es sind schon dreieinhalb Wochen her seit meinem letzten Blogposting zum Thema 64 bit Windows her. Höchste Eisenbahn also, wieder was Erhellendes zum Thema beizutragen. Diesesmal geht's um die Größen von Datentypen. Das ist dann nämlich die perfekte Überleitung zum Thema "Beliebte Fehler beim Portieren auf x64". Um das Thema näher zu illustrieren, habe ich, wie es so meine Art ist, eine kleine Kommandozeilenapplikation geschrieben, die man sich hier mit Sourcen und x86 und x64 Targets runterladen kann. Der Code für das Ganze sieht so aus:
#include <windows.h> #include <stdio.h> #include <conio.h> typedef struct _TYPE_SIZE { size_t m_stSize; LPCSTR m_szType; } TYPE_SIZE, *PTYPE_SIZE; #define CRT_ENTRY(a) {sizeof(a), #a} #define dimof(a) (sizeof(a)/sizeof(a[0])) const TYPE_SIZE g_typesize[] = { CRT_ENTRY(size_t), CRT_ENTRY(LPBYTE), CRT_ENTRY(int), CRT_ENTRY(long), CRT_ENTRY(short), CRT_ENTRY(char), CRT_ENTRY(DWORD), CRT_ENTRY(WORD), CRT_ENTRY(LPARAM), CRT_ENTRY(WPARAM), CRT_ENTRY(LRESULT), CRT_ENTRY(INT_PTR), CRT_ENTRY(UINT_PTR), CRT_ENTRY(LONG_PTR), CRT_ENTRY(LONGLONG), CRT_ENTRY(ULONG_PTR), }; int main(int /*argc*/, char* /*argv*/[]) { for (int i = 0; i<dimof(g_typesize); i++) printf("%s\t%ld bit\n", g_typesize[i].m_szType, g_typesize[i].m_stSize*8); printf ("\nINVALID_HANDLE_VALUE is 0x%I64x\n", INVALID_HANDLE_VALUE); return 0; }
Der geneigte Leser erkennt sofort, daß der Code über ein konstantes Array einer Struktur iteriert, die in einem member die Größe eines Elements und im anderen einen konstanten String mit dem Namen des Typs beinhaltet. Und ganz zum Schluß wird nochmal der Wert der Konstanten INVALID_HANDLE_VALUE ausgegeben.
Auf dem nächten Bild sieht man den Output des Programms, wenn es für Win32 auf x86 gebuildet wurde:
Dieses Ergebnis dürfte eigentlich niemanden verwundern. Aber das Ergebnis desselben Programms, wenn es für x64 gebuildet wurde, hätte mich vor gut einem Jahr noch ziemlich verdutzt:
Daß ein Pointer nun 64 bit breit ist, war ja nun wirklich zu erwarten, denn das ist es ja schließlich, was wir wollen, einen 64-bit breiten Adreßraum. Aber daß ein int und ein long immer noch die Größe eines DWORD haben, nämlich 32 bit, das hat mich dann doch extrem verwirrt, denn traditionell geht man ja davon aus, daß ein int immer so groß ist wie ein Register des Mikroprozessors. So war beispielsweise unter Win16 und MS-DOS als Targets, ein int so groß wie ein short, nämlich 16 bits. MS-DOS lief minimal auf dem Intel 8088/8086 Prozessor und Win16 minimal als Windows 3.x im Standard Mode auf einem Intel 80286 im 80286-Protected Mode, und beidesmal waren die Register 16 bit breit. Daher der int als 16 bit großer Typ. Win32 unter x86 nutzte dann die volle Registerbreite des 80386 Prozessors im 80386 protected mode und hatte daher den int native als 32 bit breiten Typ. Also sollte man doch nun annehmen, daß auf einem x64 Rechner die volle Registerbreite von 64 bits für einen int ausgenutzt wird. Pustekuchen!
Ja aber warum denn nun das? Raymond Chen,"who is, by the way, the best programmer in the world" (so Joel Spolsky) hat die Antwort. Es zerstört die Kompatibilität und viele Aplikationen würden einfach nicht mehr korrekt laufen nach dem Portieren, wenn ein int oder ein long plötzlich 64 bit breit sind. Dazu kommt, daß viele Applikationen den int in einer Weise verwenden, wo sie die 2^32 möglichen Werte gar nie ausnutzen und so auch erst recht nicht von nun 2^64 Werten profitieren würden, wenn der int nun 64 bits groß wäre. Der einzige Seiteneffekt der in diesem Fall bliebe, wäre eine lächerliche Aufblähung von Daten auf unnötig großen Speicherbedarf. Das Ganze ist auch in keinster Weise ein Verstoß gegen irgendwelche Standards, obwohl man das ja nun MS unterstellen könnte, denn auf 64-bittigen Unices ist der int tatsächlich 64 bits breit. Aber der C Standard sieht wirklich nur vor, daß ein int mindestens 16 bit breit sein muß und das war's dann.
Sodele, wahrscheinlich schreibe ich dann das nächste Mal was über diese komischen Typen im Code oben namens INT_PTR, LONG_PTR und ULONG_PTR, oder ich schreibe was über die Top Ten meiner Fehler beim Portieren von x86 binaries auf x64 binaries.
Trackback address for this post
No feedback yet
Comments are closed for this post.