linux网络编程---字节对齐、位域、网络通讯1字节对齐

字节对齐

1.对齐模数
自定义类型的自身对齐模数(struct 、class)
等同于其成员中最大的自身对齐模数
指定对齐模数
我们给编译器指定的对齐模数(在VC中使用指令:#pragma pack(n),如果不指定,在VS2010默认为8)
有效对齐模数
指定对齐模数与类型自身对齐模数的较小的值,就是实际生效的对齐模数。

2.结构体中,成员数据对齐满足以下规则:

    a、结构体中的第一个成员的首地址也即是结构体变量的首地址。
    a1结构体变量的首地址能够被其最宽基本类型成员的大小所整除; 
备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。 

    b、结构体中的每一个成员的首地址相对于结构体的首地址的偏移量(offset)是该成员数据类型大小的整数倍。

    c、结构体的总大小是对齐模数(对齐模数等于#pragma pack(n)所指定的n与结构体中最大数据类型的成员大小的最小值)的整数倍。

计算结构体内存大小tip:保证一个单位的模数空间里变量是完整保存的,或者(只在指定对齐模数小于变量所在字节情况下)如果不完整那这个空间里只能有这一个变量才可
1.先找成员变量最大类型 对应的字节(比如4)
2.一个个变量开始放入内存,保证每4个字节空间里面,成员变量都放得下,若是放不下,就跳过这个4单位空间,放
**特例:**如果成员最大为8,但指定对齐模数为2,那么放的时候按2字节放,不够填充,如 char 1字节 ,然后是double 8字节,就 1+1(填充的)+8,只要保证一个2单位的字节里面不会有多余1个的不完整的变量存着就行。

3.放完之后,如果最后一个变量不足4个字节,那么就补充够 —结果就是总占空间

各个数据类型的大小是由编译器位数所决定的!!!

一般情况下:8字节是:double (或long)

32位编译器:

char short int long float double 指针

1 2 4 4 4 8 4

64位编译器:

char short int long float double 指针

1 2 4 8 4 8 8

自定义网络通讯协议包通常都是定义成struct的形式, 而struct会自动内存对齐,这会造成结构体成员间有"空洞",传给其它平台后,其它平台弄不清楚原平台是按什么方式对齐的,只会按自己的方式解包。 解出来的结果有可能是错误的。
防止这种情况出现需要,在自定义通讯协议时,一定要让结构体(或联合)成员间都按1来对齐。

指定#pragma pack(1)1字节对齐

字节对齐链接1
字节对齐链接2

位段或位域

char instance:1;//指定 instance占1位

在前面已经提起过,在计算机中是采用二进制0和1来表示数据的,每一个0或者1占用1位(bit)存储空间,8位组成一个字节(byte),为计算机中数据类型的最小单位,如char在32bit系统中占用一个字节。但是正如我们知道的,有时候程序中的数据可能并不需要这么的字节,比如一个开关的状态,只有开和关,用1和0分别替代就可以表示。此时开关的状态只需要一位存储空间就可以满足要求。如果用一个字节来存储,显然浪费了另外的7位存储空间。所以在C语言中就有了位段(有的也叫位域,其实是一个东西)这个概念。具体的语法就是在变量名字后面,加上冒号(:)和指定的存储空间的位数。

数据在内存中的存在方式:

       1、从静态存储区分配:此时的内存在程序编译的时候已经分配好,并且在程序的整个运行期间都存在。全局变量,static变量等在此存储。

       2、在栈区分配:在程序的相关代码执行时创建,执行结束时被自动释放。局部变量在此存储。栈内存分配运算内置于处理器的指令集中,效率                                          高,但容量有限。

        3、在堆区分配:动态分配内存。用new/malloc时开辟,delete/free时释放。变量的生存期由用户指定,灵活,但会有内存泄露等问题。

对于像C++中的char这样的数据类型,它本身就是占用一个字节的大小,不会产生什么问题。但是当数制类型为int,在32bit的系统中,它需要占用4个字节(32bit),这个时候就会产生这4个字节在寄存器中的存放顺序的问题。比如int maxHeight = 0x12345678,&maxHeight = 0x0042ffc4。具体的该怎么存放呢?这个时候就需要理解计算机的大小端的原理了。

大小端

在这里插入图片描述
大端:(Big-Endian)就是把数值的高位字节放在内存的地位地址上,把数值的地位字节放在内存的地位地址上。

小端:(Little-Endian)就是把数字的高位字节放在高位的地址上,地位字节放在地位地址上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
结构体字节对齐引起的访问越界问题通常出现在以下情况下: 1. 结构体中存在字节对齐的成员变量,访问该成员变量时,可能会访问到结构体之外的内存空间。例如,如果某个成员变量的长度是4字节,但该结构体字节对齐方式是8字节,那么访问该成员变量时,可能会访问到结构体之外的4字节内存空间,从而导致访问越界。 2. 结构体中存在数组类型的成员变量,访问该数组时,可能会访问到数组之外的内存空间。例如,如果一个数组的长度是10,但该结构体字节对齐方式是16字节,那么访问该数组时,可能会访问到数组之外的6字节内存空间,从而导致访问越界。 为了避免结构体字节对齐引起的访问越界问题,可以采取以下措施: 1. 使用编译器提供的或自定义的对齐方式,以确保结构体中成员变量的对齐方式符合要求。 2. 避免在结构体中使用数组类型的成员变量,或者使用动态内存分配等方法来管理数组,以确保数组访问不会越界。 3. 避免在结构体中使用位域类型的成员变量,或者使用位运算等方法来确保位域访问不会越界。 4. 在编写代码时,注意检查结构体中的成员变量访问是否越界,可以使用断言等方法来检查访问边界。 总之,结构体字节对齐引起的访问越界问题需要引起重视,需要在编写代码时注意结构体成员变量的对齐方式和访问边界,以确保程序的正确性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值