SO问题Does GCC's __attribute__((__packed__))
…?提到__attribute__((__packed__))
执行"打包,这会在访问打包结构的字段时引入对齐问题。当直接访问字段时,编译器将对此进行说明,而不是通过指针访问它们时#34;
编译器如何确保直接访问字段?我想它在内部添加一些填充或做一些指针魔术。在下面的例子中,编译器如何确保与指针相比正确访问y
?
struct packet {
uint8_t x;
uint32_t y;
} __attribute__((packed));
int main ()
{
uint8_t bytes[5] = {1, 0, 0, 0, 2};
struct packet *p = (struct packet *)bytes;
// compiler handles misalignment because it knows that
// "struct packet" is packed
printf("y=%"PRIX32", ", ntohl(p->y));
// compiler does not handle misalignment - py does not inherit
// the packed attribute
uint32_t *py = &p->y;
printf("*py=%"PRIX32"\n", ntohl(*py));
return 0;
}
答案 0 :(得分:2)
当编译器看到符号p->y
时,由于p
的声明,它知道您正在访问结构成员,并且结构已打包。它将其转换为逐字节读取的代码,并执行必要的位移以将它们组合成uint32_t
变量。从本质上讲,它将表达式p->y
视为类似于:
*((char*)p+3) << 24 + *((char*)p+2) << 16 + *((char*p)+1) << 8 + *(char*)p
但是当您通过*py
进行间接时,编译器并不知道该变量的值来自何处。它不知道它指向一个打包的结构,所以它需要执行这种转换。声明py
指向uint32_t
,通常可以使用一次读取整个32位字的指令来访问query.exec(function(err, result))
。但是这条指令要求指针与4字节边界对齐,所以当你尝试这样做时,你会因为未对准而得到总线错误。