Reputation: 3902
I am working on an ARM project (SAMD21J18A) which reads a Bitmap file. Per the Bitmap specs, a bitmaps height will be a 4 byte long signed integer. In my struct, I am declaring the height as int32_t
. Per the BMP specs, the height can be negative, but I also need to determine the actual height because the height's negative value can be expressed in "Two's complement" (correct me if I am wrong). To do this, I am reading the buffer like so (index 22-25 are the 4 bytes for the height)
bmp.height = *(int32_t*)&header_buff[22];
However, I receive the following compiler warning:
cast increases required alignment of target type [-Wcast-align]
I'm using the arm-none-eabi-gcc
compiler.
Here is snippet of my code:
struct bitmap_t {
int32_t width;
int32_t height;
/* other properties left out for simplicity */
};
I am loading the first 54 bytes into a buffer to read the header:
struct bitmap_t bmp;
int8_t header_buff[54];
/* code to read the bmp here */
bmp.height = *(int32_t*)&header_buff[22];
Upvotes: 3
Views: 8408
Reputation: 2769
Using structures:
#pragma pack(push, 1)
struct S {
int32_t d;
};
#pragma pack(pop)
int32_t get_doubleword_packet_with_struct(uint8_t *data) {
S *s = (S *)data;
return s->d;
}
Using memcpy:
int32_t get_d_packet_with_memcpy(uint8_t *data) {
int32_t dst;
memcpy(&dst, data, sizeof(dst));
return dst;
}
My preferred way:
Define complete header into packed structure then retype bitmap into this structure, or put this structure into union with byte array and to this array copy header from bitmap.
#pragma pack(push, 1)
struct BitmapHeader {
// ... here will be all fields from bitmap header
int32_t width;
int32_t height;
// ....
};
#pragma pack(pop)
union Bmp {
BitmapHeader header;
uint8_t raw_data[sizeof(BitmapHeader)];
} bmp;
// copy data into bmp.raw_data array
// access fields from bmp.header.height ..
If you use cortex M3, M4, M7 or M33, it is possible to disable the warning, it will work. But on Cortex M0, M0+ and M23 it will not work, because unaligned access is not supported on these cores. But all my examples on M0 and M0+ will work, and compiler will use memcpy or just make 4 x read byte of the 32 bit number. This only if the struct is packed.
Upvotes: 1
Reputation: 37944
You might just use memcpy
to extract the value from header_buff
while preserving its byte ordering:
memcpy(&bmp.height, &header_buff[22], sizeof(bmp.height));
Upvotes: 2
Reputation: 34839
If header_buff
is aligned on a 4-byte boundary, then header_buff[22]
is not on a 4-byte boundary. So you can't read the height like that. You need to read the bytes one at time and use shift and OR operations to recreate the height.
Upvotes: 2