Forum: Mikrocontroller und Digitale Elektronik Strukt hat unterschiedliche länge


von Tim (Gast)


Lesenswert?

Hallo zusammen

Ich möchte den Dateiheader eines Bitmaps in ein Strukt laden.

Dazu habe ich folgendes strukt definiert:
1
struct bmp_file_header
2
{
3
  unsigned char  bfType[2];
4
  unsigned long  bfSize;
5
  unsigned long   bfReserverd;
6
  unsigned char   bfOffset[4];
7
};

system ist STM32 und ARM-GCC mit CooCox IDE

Wenn ich das ganze wie im obigen Beispiel definiere, sieht mein bfOffset 
so aus:

bfOffset  0x200001e4
  bfOffset[0]  0
  bfOffset[1]  0
  bfOffset[2]  '8'
  bfOffset[3]  0


Dies ist aber Falsch!
Die '8' müsste bei bfOffset[0] liegen

Wenn ich das Strukt wie folgt definiere:
1
struct bmp_file_header
2
{
3
  unsigned char  bfType[2];
4
  unsigned char  bfSize[4];
5
  unsigned char   bfReserverd[4];
6
  unsigned char   bfOffset[4];
7
};


Dann sieht das ganze so aus:

bfOffset  0x200001e2
  bfOffset[0]  'F'
  bfOffset[1]  0
  bfOffset[2]  0
  bfOffset[3]  0


Und genau so sehen auch die Rohdaten des BMPs aus!
Das wäre also korrekt!

Daten werden wie folgt geladen:
1
bmp_f_hdr = (struct bmp_file_header *)&ucBuffer[0];

Ich dachte unsigned long ist genau 4bytes lang...

Was läuft hier schief?

von Irgendwer (Gast)


Lesenswert?

Tim schrieb:
> Ich dachte unsigned long ist genau 4bytes lang...
>

Je nach Compilereinstellung erfolgt hierfür eine eine 
Speicherausrichtung (z.B. double-word). Wenn du also vorher zwei byte 
char hast folgen zwei Byte nichts befor dann genau auf der DWord-Granze 
der long folgt.
Bei deinem zweiten Versuch hast du nur char, da wird nichts 
ausgerichtet.

von B. S. (bestucki)


Lesenswert?

Tim schrieb:
> bmp_f_hdr = (struct bmp_file_header *)&ucBuffer[0];

Ganz ganz unschön, fehleranfällig und nicht portabel.
Stichwort: Padding Bytes

Schreib eine Funktion, der du einen Header übergeben kannst und dir eine 
korrekt befüllte Struktur zurückliefert.

von Frank K. (fchk)


Lesenswert?

Irgendwer schrieb:
> Tim schrieb:
>> Ich dachte unsigned long ist genau 4bytes lang...
>>
>
> Je nach Compilereinstellung erfolgt hierfür eine eine
> Speicherausrichtung (z.B. double-word). Wenn du also vorher zwei byte
> char hast folgen zwei Byte nichts befor dann genau auf der DWord-Granze
> der long folgt.
> Bei deinem zweiten Versuch hast du nur char, da wird nichts
> ausgerichtet.

genau. Und viele Prozessoren können keine nicht ausgerichteten Zugriffe, 
d.h 16 Bit an ungeraden Adressen und 32 Bit an nicht durch 4 teilbaren 
Adressen. Daher baut der Compiler Füllbytes ein, damit der Code (a) 
funktioniert oder (b) schneller abläuft. Falls er diese Füllbytes nicht 
einfügen soll, musst Du ihm das extra sagen (#pragma oder __attribute() 
oder wie auch immer, compilerspezifisch)

fchk

von c-hater (Gast)


Lesenswert?

Tim schrieb:

> Dazu habe ich folgendes strukt definiert:

Da stellt sich bereits die erste Frage, warum hast du sie überhaupt 
selber deklariert? Du machst doch sonst auch bloß Copy&Paste, warum also 
nicht auch die Strukturdeklarationen?

>   unsigned char   bfOffset[4];

Das ist einfach Blödsinn. bfOffBits (so heißt das Feld eigentlich) ist 
ein 32Bit unsigned integer, nix anderes. War es noch nie und wird es 
auch nie sein.

> Wenn ich das ganze wie im obigen Beispiel definiere, sieht mein bfOffset
> so aus:
>
> bfOffset  0x200001e4
>   bfOffset[0]  0
>   bfOffset[1]  0
>   bfOffset[2]  '8'
>   bfOffset[3]  0

Das wäre ein sehr ungewöhnlicher Inhalt für das Feld...

Wahrscheinlich ein "Packing"-Problem. Oder anders ausgedrückt: falsche 
Strukturdeklaration. Ja, es hat seine Vorteile, wenn man die beschissene 
Sprache tatsächlich beherrscht, zu deren Verwendung man sich freiwillig 
entschieden hat...

> Die '8' müsste bei bfOffset[0] liegen

Das wäre dann aber immer immer noch ein ziemlich ungewöhnlicher Wert an 
dieser Stelle...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ich werfe hier für die weitere Recherche einfach mal das Wort 
"Alignment" in die Runde...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.