[C++] Problem z wielkością struktury - align?

0

Mam następujący problem, pisze program który ma mi rozmazywać bitmapy 8, 16, 24 i 32 bitowe i utknąłem już na początku, a mianowicie stworzyłem sobie strukturę mająca reprezentować nagłówek bmp by nie bawić się z offsetami tylko zrobić to skrycie, struktura wygląda następująco:

typedef unsigned char byte;     // 1 bajt
typedef unsigned short word;    // 2 bajty
typedef unsigned long dword;    // 4 bajty
typedef struct BMP_HEADER{
    word    bfType;             // sygnatura
    dword   bfSize;             // wielkosc calego pliku w bajtach
    word    Res1;               // zarezerwowane
    word    Res2;               // zarezerwowane
    dword   bfOffBits;          // offset danych obrazowych
    dword   biSize;             // wielkosc naglowka
    dword   biWidth;            // szerokosc obrazu
    dword   biHeight;           // wysokosc obrazu
    word    biPlanes;           // liczba warstw kolorow
    word    biBitCount;         // liczba bitow na pixel
    dword   biCompression;      // algorytm konmresji
    dword   biSizeImage;        // rozmiar samego rysunku
    dword   biXPelsPerMeter;    // rozdzielczosc pozioma
    dword   biYPelsPerMeter;    // rozdzielczosc pionowa
    dword   biClrUsed;          // liczba kolorow w palecie
    byte    biClrImportant;     // liczba ważnych kolorów w palecie
    byte    biClrRotation;      // flaga muwi czy ma następowac rotacja palety
    word    biReserved;         // zarezerwowane
}BMP_HEADER;

to wygląda tak, że wczytuje 54 pierwsze bajty pliku, i definiuje pointer BMP_HEADER wskazujący na te dane, ale całość nie działa prawidłowo bo kompilator chce mnie na siłę uszczęśliwić dodając mi dodatkowe 2 bajty miedzy bfType, a bfSize po to by procesor mógł odczytać dword’y za pomocą jednego, a nie dwóch dostępów do ramu. Ja sobie z tym radze tak, że do struktury dodaję na samym początku struktury dodatkowe 2 bajty (wtedy kompilator już mi się nie wtrąca) i jak definiuje pointer BMP_HEADER wskazujący na dane nagłówka w pamięci to wskazuje nie na te dane ale na dane o 2 bajty wcześniej czyli:

byte * fBitmap;
fread(fBitmap, 1, 54, pFile);
(...)
BMP_HEADER * iBitmap;
iBitmap = (BMP_HEADER*) (fBitmap - 2);

gdzie pFile to uchwyt do pliku. Ok to działa, ale jeśli struktura wyglądała by inaczej to kompilator wtrącał by się dodatkowo wszędzie tam gdzie adres dword'a nie jest podzielny przez 4 a tego raczej nie chcę i teraz mam pytanie jak to wyłączyć? Jak zrobić tak aby kompilator do tej struktury mi się nie wtrącał?

0

W GNU świecie:

struct {
  /* ... */
} foo __attribute__((packed));

w MSVC:

#pragma pack(push, 1)
/* strukurka */
#pragma pack(pop)

Dopisek:

I pamiętaj że nie na wszystkich platformach dostęp do niewyrównanych zmiennych jest dozwolony.
No i niektóre platformy mają inną kolejność bajtów (LE/BE)
Lepiej wrzucić nagłowek do unsigned char buf[54]; a potem ręcznie:

   struct BMP_HEADER hdr;

   hdr.bfType = buf[0] << 8 | buf[1];
   hdr.bfSize = buf[2] << 24 | buf[3] << 16 | buf[4] << 8 | buf[5];
   /* albo odwrotnie ;-) */
0

Serdeczne dzięki za odpowiedź, pisze tylko pod x86, ale dzięki za wskazówkę.

1 użytkowników online, w tym zalogowanych: 0, gości: 1