最近在看《UNIX网络编程》,发现一个问题,始终无法解决,请大神帮忙答疑解惑。
我们知道,通常情况下,结构体是有对齐的需求的,我在win32下用gcc,int大小是4, char大小是1,默认采用自然对齐,定义了两个结构体和一个字符数组:
typedef struct
{
char a1;
char a2;
char a3;
}A;
typedef struct
{
int b1;
int b2;
}B;
char buff[1024] = {0};
很明显,char是1字节对齐,A是1字节对齐,sizeof(A) = 3, B是4字节对齐. sizeof(B) = 8;
在《UNIX网络编程》一书中,经常有类似于下面的这种做法:
A* a = (A*)buff;
XXXXXXXXX; //对a进行操作
B* b = (B*) (buff +sizeof(A));
b->b1......;
b->b2......; //对b进行操作
我之前对字节对齐的理解是这样的:char*强转成A*没有问题,因为他们都只要求起始地址是1的整数倍,但是强转成B*似乎会出问题。假设buff本身恰好处于4的整数倍的地址(貌似有些系统默认栈内存起始都是4对齐),那么这样一来buff +sizeof(A)就一定不能满足是4的整数倍,从而使得强转后的指针b无法满足B的对齐条件(B是4字节对齐所以B的首地址必须是4 的整数倍),这个时候使用b->b1或者b->b2这样的方式访问数据似乎就会有一些问题。
看到网上有些资料说,这种情况在x86上是允许的,只是会使存取效率降低,而在ARM上会导致错误。我本人之前在ARM上也踩过类似的坑,所以对这个特别关注。不过我感觉Steven大神的代码不应该有问题的,所以有些怀疑自己之前所理解的内容。不知为各位大神对此有什么见解呢?