cast 增加了目标类型与指针的对齐要求
cast increases required alignment of target type with pointer
我正在处理读取位图文件的 ARM 项目 (SAMD21J18A)。根据位图规范,位图高度将是一个 4 字节长的有符号整数。在我的结构中,我将高度声明为 int32_t
。根据 BMP 规范,高度可以是负数,但我还需要确定实际高度,因为高度的负值可以用 "Two's complement" 表示(如果我错了请纠正我)。为此,我正在读取缓冲区(索引 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 个字节加载到缓冲区中以读取 header:
struct bitmap_t bmp;
int8_t header_buff[54];
/* code to read the bmp here */
bmp.height = *(int32_t*)&header_buff[22];
如果 header_buff
在 4 字节边界上对齐,那么 header_buff[22]
是 而不是 4 字节边界。所以你不能像那样读取高度。您需要一次读取一个字节并使用移位和或运算重新创建高度。
您可以只使用 memcpy
从 header_buff
中提取值,同时保留其字节顺序:
memcpy(&bmp.height, &header_buff[22], sizeof(bmp.height));
使用结构:
#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;
}
我的首选方式:
将完整的 header 定义为压缩结构
然后将位图重新键入此结构,或将此结构与字节数组合并,然后从位图复制 header 到此数组。
#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 ..
如果你使用cortex M3、M4、M7或M33,可以禁用警告,它将起作用。但在 Cortex M0、M0+ 和 M23 上它不起作用,因为这些内核不支持未对齐访问。但是我在 M0 和 M0+ 上的所有示例都可以工作,并且编译器将使用 memcpy 或只生成 4 x 32 位数字的读取字节。仅当结构被打包时才如此。
我正在处理读取位图文件的 ARM 项目 (SAMD21J18A)。根据位图规范,位图高度将是一个 4 字节长的有符号整数。在我的结构中,我将高度声明为 int32_t
。根据 BMP 规范,高度可以是负数,但我还需要确定实际高度,因为高度的负值可以用 "Two's complement" 表示(如果我错了请纠正我)。为此,我正在读取缓冲区(索引 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 个字节加载到缓冲区中以读取 header:
struct bitmap_t bmp;
int8_t header_buff[54];
/* code to read the bmp here */
bmp.height = *(int32_t*)&header_buff[22];
如果 header_buff
在 4 字节边界上对齐,那么 header_buff[22]
是 而不是 4 字节边界。所以你不能像那样读取高度。您需要一次读取一个字节并使用移位和或运算重新创建高度。
您可以只使用 memcpy
从 header_buff
中提取值,同时保留其字节顺序:
memcpy(&bmp.height, &header_buff[22], sizeof(bmp.height));
使用结构:
#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;
}
我的首选方式:
将完整的 header 定义为压缩结构 然后将位图重新键入此结构,或将此结构与字节数组合并,然后从位图复制 header 到此数组。
#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 ..
如果你使用cortex M3、M4、M7或M33,可以禁用警告,它将起作用。但在 Cortex M0、M0+ 和 M23 上它不起作用,因为这些内核不支持未对齐访问。但是我在 M0 和 M0+ 上的所有示例都可以工作,并且编译器将使用 memcpy 或只生成 4 x 32 位数字的读取字节。仅当结构被打包时才如此。