1

如果 TStruct 已打包,则此代码以 Str.D == 0x00223344(而不是 0x11223344)结尾。为什么?ARM GCC 4.7

#include <string.h>

typedef struct {
   unsigned char B;
   unsigned int D;
} __attribute__ ((packed)) TStruct; 

volatile TStruct Str;

int main( void) {
  memset((void *)&Str, 0, sizeof(Str));
  Str.D = 0x11223344;
  if(Str.D != 0x11223344) {
     return 1;
  }
  return 0;
}
4

1 回答 1

1

我猜您的问题与未对齐的访问无关,而是与结构定义有关。int不一定是 32 位长。根据 C 标准,int 至少为 16 位长,char 至少为 8 位长。

我的猜测是,您的编译器优化了 TStruct,所以它看起来像这样:

struct {
   unsigned char B : 8;
   unsigned int D : 24;
} ...;

当您分配0x11223344给 时Str.D,根据 C 标准,编译器必须只确保至少有 16 位 ( 0x3344) 被写入Str.D. 您没有指定它Str.D是 32 位长,只是它至少是 16 位长。

您的编译器也可以像这样安排结构:

struct {
   unsigned char B : 16;
   unsigned int D : 16;
} ...;

B至少 8 位长,D至少 16 位长,都可以。

可能,您想要做的是:

#include <stdint.h>

typedef struct {
   uint8_t B;
   uint32_t D;
} __attribute__((packed)) TStruct;

这样,您可以确保 32 位值0x11223344正确写入Str.D. 对 __packed 结构使用大小受限类型是个好主意。
至于结构内成员的非对齐访问,编译器应该处理它。如果编译器知道结构定义,那么当您访问Str.D它时,应该注意任何未对齐的访问和位/字节操作。

于 2017-12-14T15:06:31.353 回答