struct padding und #pragma pack(1)
-
Hallo,
ich muss für eine Uni-Aufgabe ein bitmap file einlesen, es manipulieren und wieder speichern. Dabei bin ich auf dass padding/alignment problem von structs gestossen. Der Bitmap fileheader setzt sich aus 14 bytes zusammen, und zwar so:
typedef struct { unsigned short int signature; unsigned int size; unsigned int reserved; unsigned int bitsOffset; } BMP_HEADER;Wenn allerdings die Wortgrösse des Systems 4 bytes beträgt, werden vom compiler nach signature 2 padding bytes eingefügt, damit size am anfang eines wortes liegt. Nach dem kompilieren hat die oben erwähnte struct eine Grösse von 16 statt 14. Das ganze hat soweit ich es verstanden habe den Sinn, dass pro leseoperation ein wort gelesen werden kann, und sonst für das lesen vom rest des structs jeweils 2 operationen benötigt würden.
Mein Problem liegt darin, dass der bitmap header GENAU 14 bytes gross ist, und wenn ich ihn in die struct lade, die gepadded wurde, stimmen die werte nicht mehr. Nach einigem googlen habe ich die präprozessor direktive #pragma pack(1) gefunden, die das padding des compilers unterbindet. Mit dieser direktive funktioniert es dann auch einwandfrei. Leider soll #pragma pack(1) nicht von allen compilern unterstützt werden, und ist somit nicht crossplatform-kompatibel. Des weiteren dürfte es wesentlich langsamer sein, als mit padding, wegen der doppelten Speicherzugriffe.
Meine Frage ist nun, wie kann man das Problem lösen, ohne #pragma pack(1) zu verwenden ?
-robert
-
Hallo
Ich bin mir selber nicht sicher und möchte keine Lügen verbreiten, aber gilt die Strukturenoptimierung nicht nur bei Visual Studio?
Mfg.
way
-
Indem du nicht ein
structeinliest, sondern die einzelnen Werte. Also in dieser Reihenfolgen:
- read signature
- read size
- read reserved
- read bitsOffsetDes Weiteren ist der präsentierte Code C. In C++ würde man es so machen:
struct BMP_HEADER { unsigned short int signature; unsigned int size; unsigned int reserved; unsigned int bitsOffset; };Oder am besten gleich eine Klasse mit Getter und Setter. Oder bist du einfach im Forum?
Grüssli
-
Du musst die Werte des Header einzeln aus der Datei lesen und von da einzeln in die Struktur schreiben. Der Compiler darf das struct so ziemlich organisieren wie er will und endianess kann dir auchnoch einen Strich durch die Rechnung machen.
geloescht
-
da bin ich wohl auf der Leitung gestanden, danke für die Hilfe!
-
Dravere schrieb:
Des Weiteren ist der präsentierte Code C. In C++ würde man es so machen:
Danke, hab ich nicht gewusst dass c++ structs anders aussehen.
-
pulse00 schrieb:
Danke, hab ich nicht gewusst dass c++ structs anders aussehen.
Dein Code ist natürlich auch gültiges C++. Nur war es in C noch nötig, das
typedefhinzuschreiben, um den Strukturnamen gleich als Typbezeichner zu wählen.In C hättest du ohne
typedefbei der Deklaration immer sowas schreiben müssen:struct BMP_HEADER var;In C++ kannst du dir das
structsparen.