我正在研究一个读取Bitmap文件的ARM项目(SAMD21J18A)。根据位图规范,位图高度将是4字节长的有符号整数。在我的结构中,我将高度声明为int32_t
。根据BMP规格,高度可以是负值,但我还需要确定实际高度,因为高度的负值可以用"二进制补码"表示。 (如果我错了,请纠正我)。为此,我正在读取缓冲区(索引22-25是高度的4个字节)
bmp.height = *(int32_t*)&header_buff[22];
但是,我收到以下编译器警告:
cast increases required alignment of target type [-Wcast-align]
我正在使用arm-none-eabi-gcc
编译器。
以下是我的代码片段:
struct bitmap_t {
int32_t width;
int32_t height;
/* other properties left out for simplicity */
};
我将前54个字节加载到缓冲区中以读取标题:
struct bitmap_t bmp;
int8_t header_buff[54];
/* code to read the bmp here */
bmp.height = *(int32_t*)&header_buff[22];
答案 0 :(得分:2)
您可以使用memcpy
从header_buff
中提取值,同时保留其字节顺序:
memcpy(&bmp.height, &header_buff[22], sizeof(bmp.height));
答案 1 :(得分:1)
如果header_buff
在4字节边界上对齐,则{4}边界上的header_buff[22]
不 。所以你不能那样读高度。您需要一次读取一个字节,并使用shift和OR操作重新创建高度。
答案 2 :(得分:1)
使用结构:
#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;
}
使用memcpy:
int32_t get_d_packet_with_memcpy(uint8_t *data) {
int32_t dst;
memcpy(&dst, data, sizeof(dst));
return dst;
}
我的首选方式:
将完整标题定义为打包结构 然后将位图重新键入该结构,或将该结构与字节数组合并,并从位图复制到该数组的复制头。
#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 ..
如果您使用皮质M3,M4,M7或M33,则可以禁用该警告,它将起作用。但是在Cortex M0,M0 +和M23上将无法使用,因为这些内核不支持未对齐的访问。但是我在M0和M0 +上的所有示例都可以使用,并且编译器将使用memcpy或仅使32位数字的4个字节读取。仅当该结构被打包时。