cast增加了目标类型与指针的对齐

时间:2017-12-02 21:51:04

标签: c gcc arm gcc-warning atmelstudio

我正在研究一个读取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];

3 个答案:

答案 0 :(得分:2)

您可以使用memcpyheader_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个字节读取。仅当该结构被打包时。