Zitat von
mkinzler:
Das macht nicht der Compiler sondern der Prozessor.
Nein. Der Compiler hält soviel Space vor durch den erzeugten Code und beachtet bei SizeOf() immernoch den eigentlichen Typ.
@christian_r:
Der Compiler führt ein Alignment durch bei der Generierung deines Codes, damit der Prozessor dort nicht extra arbeiten muss. Wenn du eine Variable als Byte definierst, dann hält er 32 Bit vor (32 Bit Compiler), nutzt aber nur ein Byte davon. Dadurch kann der Prozessor immer 32 Bit beim Lesezugriff holen bzw. Schreiben. Der vom Compiler generierte Code wiederrum achtet aber darauf, nur die von dir definierten 8 Bit zu nutzen.
Hintergrund:
Wenn der Compiler einen echten 8 Byte nehmen sollte und du diesen liest, liest die CPU trotzdem immer einen Wert, der so gross ist wie sein Datenbus ist, ein. Dies ist die kleinste Einheit, die er bei einer Anfrage an den
RAM stellen kann, da dieser auch einen solch breiten Datenbus hat. Er hat also beim Lesezugriff auf die adressierte
RAM Stelle immer den gesamten Datenbus mit den Daten belegt. Wenn nun der Prozessor nur 8 Bit haben will (1 Byte), dann gehen über den Datenbus trotzdem 32 Bit rüber, gehen durch den Cache, etc. und die CPU schmeisst nachher 24 Bit von den eingelesenen Werten weg, da es nur 8 Bit braucht. Dies ist ein extra Aufwand von der CPU.
Wenn alle Datentypen versuchen eine durch die Breite des Datenbusses teilbare Grösse zu haben, dann kann der Prozessor optimal arbeiten. Wenn du z.B. einen Record mit einen Word und einen Integer nacheinander definierst, dann werden beide an einer durch 4 teilbaren Adresse angelegt. Der Record wird 16 Byte gross sein, was optimal für die CPU ist, aber nachteilig, wenn du z.b. eine Datei einlesen willst, der diese Struktur enthält, weil dort das Word nur 16 Bit gross sein soll. Dafür kannst du dann das "packed" Schlüsselwort verwenden. Damit schaltest du das Aligment ab und alle Werte liegen in ihrer definierten Grösse nacheinander im Speicher. Damit kommt es aber auch dazu, dass der Integer auf einer nur durch 2 teilbaren Adresse liegt. Da der Datenbus aber 32 Bit gross ist, muss die CPU, um diesen Integerwert zu lesen, zweimal lesen. Einmal adressiert er die Adresse mit den oberen 16 Bit des integers und liest diese ein. Am Datenbus liegen dann oben 16 Bit das Word an und in den unteren 16 Bit die oberen 16 Bit des Integers an. Diese holt sich die CPU raus und merkt sich diese um danach die darauffolgende Adresse (4 Bytes weiter) zu lesen. In diesen findet er in den oberen 16 Bit (der 32 Bits die am Datenbus anliegen) die für den Integer unteren 16 Bits. Diese setzt er zusammen und erhält nun endlich deinen Integer den du wolltest. Aber er musste zweimal lesen um diesen zu erhalten.
Grundlegend sollte das Problem nun verständlich sein. Es ist immer zu versuchen die Daten an aligned Adressen abzulegen und das versucht der Compiler von Haus aus. Ungerade Adressen sind ein graus für die CPU, weil er zweimalig lesen muss. Heutzutage sorgen Sprungvorhersage, Adressvorhersage und Cache pre filling dafür, dass nebenbei die CPU ermittelt, wo der Code ein paar Opcodes später hinspringt, was er als nächstes adressiert bzw. lesen will, um diese Aktionen schon vorher zu erledigen. Da wird dann mal schon ein paar Opcodes zuvor eine Adresse vom Hauptspeicher ausgelesen, die erst später vom Code adressiert wird. Auch wird vorhergesagt, wohin bestimmte Verzweigungen gehen, um im Idealfall den Code schon in den Cache geladen zu haben, etc. Im besten Falle fallen WaitStates weg (Wartezyklen die die CPU einlegt zwischen Adressierung und Freigabe des Datenbusses) und der Cache hält fast alle Daten vor und im schlimmsten Falle war die Vorhersage falsch und alle Daten müssen besorgt werden und der gesamte Cache enthält falsche Daten und muss geleert werden. All diese Bemühungen der CPU und dieser kleiner Helferleins kann man sich gut in CPU internen Register (MSR) anschauen und auch deren Effizienz ermitteln. Mit diesen Registern und ein paar Anleitungen vom CPU Hersteller, können die Compiler optimierten Code bauen, die auch einwandfrei von diesen Helferleien unterstützt wird und deren falschen Voraussagen auf ein minimum reduzieren.
Aber egal, das war nicht mehr die Frage an sich...