Question

#include <cstdio>

struct BMP_Header
{
    unsigned char MN[2];
    unsigned int fileSize;
    char unused[4];
    unsigned int bitmapOffset;
};

struct DIB_Header
{
    unsigned int headerSize;
    unsigned int width;
    unsigned int height;
    unsigned short planes;
    unsigned short bits;
    unsigned int compresion;
    unsigned int rawDataSize;
    unsigned int hResolution;
    unsigned int vResolution;
    unsigned int palleteColors;
    unsigned int importantColors;
};

int main() {
    BMP_Header header1;
    DIB_Header header2;
    FILE *f = fopen("1.bmp", "rb");
    fread(&header1, 1, sizeof(BMP_Header), f);
    fread(&header2, 1, sizeof(DIB_Header), f);
    fclose(f);
    char *ptr = ((char*)&header1) + sizeof(unsigned short);
    printf("%d %d\n%d %d\n%d =?= %d\n", ptr - (char*)&header1, (char*)&(header1.fileSize) - (char*)&header1, sizeof(BMP_Header), sizeof(unsigned short), *(int*)ptr, header1.fileSize);
}

Can anyone tell me why my program outputs this:

2 4
16 2
90 =?= 0

But should output this:

2 2
14 2
90 =?= 90

I dont know why fileSize in BMP_Header have 4 offset if 2 chars(MN in BMP_Header) have 2 bytes size

I'm using MinGW

Was it helpful?

Solution

This is because C and C++ compilers pad structures by adding one or more bytes in between. This is done for efficiency of data access.

For example, in the first case the compiler added two bytes between the two-byte MN member and the fileSize, which is an int, presumably because in your target architecture it is faster to access an int when its address is divisible by 4.

Note: you can use offsetof(struct BMP_Header, fileSize) instead of doing the pointer manipulation to compute the offset of the corresponding element of the struct.

OTHER TIPS

Many ABIs specify that a structure should be aligned according to their largest member. In your case, the largest member of BMP_Header is 4 bytes in size, so it is aligned to 4 bytes. This means that some padding needs to be added (as you only have 14 bytes worth of value representation). The padding is added between the MN and filesize members, so that all members are aligned to a 4 byte boundary.

Note that this is completely dependent on the machine you are targeting and you can't rely on the results if you're compiling cross-platform.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top