c语言结构体的字节对齐,关于c:c语言结构体字节对齐详解

1.什么是字节对齐

在c语言的构造体外面个别会依照某种规定去进行字节对齐。

咱们先看一段代码:

struct st1

{

char name;

double age;

char sex;

};

//32位下 sizeof(struct st1) = 16

//64位下 sizeof(struct st1) = 24

struct st2

{

char a;

char b;

char c;

};

//32位和64位下, sizeof(struct st2)都是3个字节

从以上后果能够看出,构造体st1在32位下是依照4个字节来对齐的,在64位下则是依照8个字节来对齐的,构造体st2则不论32位还是64位则都是依照1个字节对齐的。

那么咱们能够总结出对齐规定如下:

在所有构造体成员的字节长度都没有超出操作系统根本字节单位(32位操作系统是4,64位操作系统是8)的状况下,依照构造体中字节最大的变量长度来对齐;

若构造体中某个变量字节超出操作系统根本字节单位,那么就依照零碎字节单位来对齐。

留神:并不是32位就间接依照4个字节对齐,64位依照8个字节对齐。

2.为什么要有字节对齐

首先遍及一点小常识,cpu一次能读取多少内存要看数据总线是多少位,如果是16位,则一次只能读取2个字节,如果是32位,则能够读取4个字节,并且cpu不能跨内存区间拜访。

假如有这样一个构造体如下:

struct st3

{

char a;

int b;

};

//那么依据咱们第1节所说的规定,在32位零碎下,它就应该是8个字节的。

假如地址空间是相似上面这样的:

在没有字节对齐的状况下,变量a就是占用了0x00000001这一个字节,而变量b则是占用了0x00000002~0x000000005这四个字节,那么cpu如果想从内存中读取变量b,首先要从变量b的开始地址0x00000002读到0x0000004,而后再读取一次0x00000005这个字节,相当于读一个int,cpu从内存读取了两次。

而如果进行字节对齐的话,变量a还是占用了0x00000001这一个字节,而变量b则是占用了0x00000005~0x00000008这四个字节,那么cpu要读取变量b的话,就间接一次性从0x00000005读到0x00000008,就一次全副读取进去了。

所以说,字节对齐的根本原因其实在于cpu读取内存的效率问题,对齐当前,cpu读取内存的效率会更快。然而这里有个问题,就是对齐的时候0x00000002~0x00000004这三个字节是节约的,所以字节对齐实际上也有那么点以空间换工夫的意思,具体写代码的时候怎么抉择,其实是看集体的。

3.手动设置对齐

什么状况下须要手动设置对齐:

设计不同CPU下的通信协议,比方两台服务器之间进行网络通信,共用一个构造体时,须要手动设置对齐规定,确保两边构造体长度始终;

编写硬件驱动程序时寄存器的构造;

手动设置对齐形式有两种:

代码里增加预编译标识:

//用法如下

#pragma pack(n)//示意它前面的代码都依照n个字节对齐

struct st3

{

char a;

int b;

};

#pragma pack()//勾销依照n个字节对齐,是对#pragma pack(n)的一个反向操作

//这里计算sizeof(st3)=5

下面这两行其实就相似于开车的时候,走到某一段路的时候,发现一个限速60公里的指示牌,过了那一段路当前,又会有解除限速60公里的指示牌。

定义构造体时:

//用法如下

struct bbb

{

char a;

int b;

}__attribute__((packed));//间接依照理论占用字节来对齐,其实就是相当于依照1个字节对齐了

//这里计算sizeof(st3)=5

4.构造体比拟办法

能够应用内存比拟函数memcpy进行构造体比拟,但因为构造体对齐可能会有填充位不统一的状况,此时须要留神:

设置为1个字节对齐,使它没有空位;

当时对构造体进行初始化;

memcpy(char *dest, const char* src, int len); //头文件#include

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值