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 字节边界。所以你不能像那样读取高度。您需要一次读取一个字节并使用移位和或运算重新创建高度。

您可以只使用 memcpyheader_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 位数字的读取字节。仅当结构被打包时才如此。