结构体字节对齐和网络字节序

前不久,在C++程序中碰到一个有关结构体字节对齐的问题。c++

一。问题描述数组

在程序中,定义了一个结构体,以下:
typedef struct
{
   char name[33];
   int ID;
   int  age;
} PERSON;网络

声明了一个该结构体的数组:
PERSON peo[30];布局

当从结构体中取出ID字段给一个int类型的局部变量赋值时,却出现异常.
好比结构体中的字段都已经有初始值
peo[0].ID =4;调试

下面的赋值语句
int tempID = peo[0].ID;
却不能正确获得数值4,tempID获得的是67108864.
经检查67108864是4在高位时的数值大小.
赋值时原本应该是取内存中的四个Bytes:"04 00 00 00"
但是取值时倒是用"00 00 00 04" 的方式.
在调试过程当中,从peo[0].ID取值是正确的,获得数字4,可程序执行上面赋值语句后:
tempID仍是获得的是67108864.内存

也就是说,在调试器中取值是正确的,汇编后的程序取值倒是不正确的.
程序在开始用了的很长一段时间并无出现这种问题,这个问题是最近才发生的.
真是百思不得其解。还有一点是明确的,程序涉及到网络传输。编译器

但是若是把结构体中的字符数组大小由33改成36,一切正常了!编译

原理上确定是结构体的位对齐问题,但为何之前编译使用没出问题,如今编译才发生呢?
应该怎么解决呢?社区

二。寻找问题的缘由。变量

通过CSDN社区各位老大的帮助,而且本身仔细去了解程序中的编译条件部分,原则上理解了这问题的本质所在。

发如今网络模块中使用到了"#pram pack(1)"这样的编译条件,而其它模块则没有加入这种编译条件。

而CSDN中其中一个大虾是这样解释的:“对齐方式是给编译器看的,编译器根据这个来决定内存布局。一旦编译成二进制文件内存布局就已经肯定了,若是两段代码对同一个结构使用的对齐方式不一样,那么就会对内存里的值作出了不一样的解释,赋值的一方认为char[33]占了36个字节,从第37个字节填写04 00 00 00,但是读取的一方认为char[33]只有33个字节,那就从第34个字节处取四个字节看成ID。”

此次网友的解释,我认为指出了问题的本质所在:“若是两段代码对同一个结构使用的对齐方式不一样,那么就会对内存里的值作出了不一样的解释”。咱们的程序给结构体初始化部分是按VC编译器中默认的结构体8字节对齐,而在网络模块中,因为使用了"#pram pack(1)",结果从结构体中取值时,编译器认为结构体是按1字节对齐,最终致使了问题的产生。

三。解决方法

为了解决这个问题,就须要程序中全部的代码对同一个结构体都使用同一种对齐便可。

会有两种解决办法:
一是把网络模块中的"#pram pack(1)"去掉,结构体都是按VC编译器中默认的结构体8字节方式对齐。
二是设置结构体按1字节方式进行对齐,程序全部模块都按这种对齐方式编译。

设置在VC的"project"->"setting..."->"c/c++":struct member aligment改为1 Bytes.

相关文章
相关标签/搜索