Strukt hat unterschiedliche länge

Gast #3694957
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?
Gast #3694975
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.
#3694999
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
Gast #3695103
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...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren