"Lücke" beim casten in ein struct
-
Hallo Leute,
ich bin heute auf ein Merkwürdiges Verhalten von gcc gestoßen. Wenn ich diesen Code ausführe
#include <stdio.h> struct mystruct { unsigned short a; unsigned int b; }; int main() { char *mystr = "AABBCCDD"; struct mystruct *test = (struct mystruct *) mystr; printf("a=%X\n", test->a); printf("b=%X\n", test->b); return 0; }
erhalte ich
a=4141 b=44444343
Es wurden also die beiden Zeichen "BB" übersprungen. Wenn ich
unsigned int b;
zu
unsigned short b;
ändere bekomme ich jedoch wie erwartet
a=4141 b=4242
Mein System läuft unter Ubuntu 10.10, gcc Version ist 4.4.5
Kann mir bitte jemand erklären was da schief läuft und wie ich es schaffe die "Lücke" zu schließen?Viele Grüße
Klaus
-
Der interne Aufbau eines structs bleibt dem Compiler überlassen, er kann beliebig Lücken einbauen, wenn ihm das performancetechnisch ratsam vorkommt. Das nennt man dann Padding und Alignment. Üblicherweise werden aber auch Schalter angeboten um dies abzuschalten, aber die kann ich nicht auswendig, weil ich es bevorzuge Programme zu schreiben, die solche Tricksereien gar nicht nötig haben.
-
ein short ist 2 byte groß ein int 4 byte desshalb ist die eine zahl auch so groß
-
Darum gibt es auch die Funktion http://linux.die.net/man/3/offsetof (hat sogar ne kleine Erklärung deines Problems).
Lösung: Bitfields verwenden.
-
SeppJ schrieb:
... die solche Tricksereien gar nicht nötig haben.
Das sind keine Tricksereien, manchmal ist es einfach (leider) notwendig.
Zum Beispiel, wenn bei der Entwicklung eines fremden Dateiheaders einfach nicht an das Padding gedacht wurde, oder das Dateiformat noch aus Urzeiten stammt.
Schau dir mal den tga-Header an, ich habe keine Ahnung wie alt das Format ist, ohne explizite Compileranweisungen bezüglich des Paddings geht's jedenfalls nicht.
-
-
offsetof
suggeriert, eine Funktion zu sein, obwohl es natürlich in Wirklichkeit ein Makro ist.
-
Die Wörter lassen sich schneller verarbeiten wenn sie auf 'geraden' Adressen liegen. Das soll heißen das 2-Byte Wörter auf durch 2 teilbare Adressen liegen.
bei 4-Byte und 8-Byte entsprechend durch 4 und 8 teilbar.Es gibt Prozessoren und Programmiersprachen bei denen es nicht anders geht.
Die x86 können auch mit 'ungeraden' Adressen arbeiten, dann aber etwas langsamer.
-
offshore schrieb:
offsetof
suggeriert, eine Funktion zu seinWomit?
-
mngbd schrieb:
offshore schrieb:
offsetof
suggeriert, eine Funktion zu seinWomit?
eigentlich gar nicht, auf der man-page steht drauf, dass es sich um ein Makro handelt.
-
supertux schrieb:
eigentlich gar nicht
Finde ich auch. Wenn man's nicht weiss, darf man's für einen Compilezeit-Operator halten, aber nicht für eine Funktion.
-
Es ist allgemein eine gute Idee, Strukturen elementweise zu behandeln. Dann hat man auch keine Probleme mit Padding und Alignment.
-
Wow, vielen Dank für die ganzen Antworten!
Ich habe das Programm jetzt mit der Option "-fpack-struct" compiliert und es funktioniert
Ich weiß, dass das nur eine Notlösung ist, aber für meine Zwecke funktioniert es.
Danke für den Tipp. Ich lese einen Datenstrom von einem Socket und möchte mit Hilfe von structs auf einzelne Header-Felder zugreifen.@Tachyon: Was meinst du mit elementweise behandeln?
-
#include <stdio.h> #include <string.h> struct mystruct { unsigned short a; unsigned int b; }; int main() { char const * mystr = "AABBCCDDEEFF"; struct mystruct test; /*Padding/Alignment egal, da immer an die richtige Stelle kopiert,*/ /*und nicht nur reinterpretiert wird*/ memcpy(&test.a, mystr, sizeof(test.a)); memcpy(&test.b, mystr + sizeof(test.a), sizeof(test.b)); printf("a=%X\n", test.a); printf("b=%X\n", test.b); return 0; }