在C语言的结构中,字节对齐通常是按照一定的规则进行的。本文将介绍如何实现,有一定的参考价值,有兴趣的可以了解一下。
:
目录
1.什么是字节对齐?
2.为什么要有字节对齐?
3.手动设置校准
4.结构比较法
1.什么是字节对齐?
在C语言的结构中,字节对齐通常是按照一定的规则进行的。
让我们先来看一段代码:
结构st1
{
字符名称;
双倍年龄;
迷人的性爱;
};
//32位以下的Sizeof(struct st1 )=16
//sizeof(struct st1)=24,64位以下
结构st2
{
char a;
char b;
char c;
};
//sizeof(struct st2)在32位和64位中都是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不能跨内存区间访问。
假设有如下这样的结构:
结构st3
{
char a;
int b;
};
//那么按照我们第一节说的规则,32位系统应该是8个字节。
假设地址空间是这样的:
在没有字节对齐的情况下,变量A占用一个字节0x00000001,而变量B占用四个字节0x00000002 ~0x000000005。如果cpu想要从存储器中读取变量B,它必须首先读取变量B的起始地址0x 00000002到0x0000004,然后再次读取0x00000005的字节。
如果进行字节对齐,变量A仍然占用0x00000001的一个字节,而变量B占用0x00000005~0x00000008的四个字节。如果cpu要读取变量B,直接从0x00000005到0x0000008一次性读取,一次全部读出。
所以字节对齐的根本原因在于cpu读取内存的效率。字节对齐后,cpu读内存的效率会更快。但是这里有一个问题,就是对齐的时候浪费了0x00000002 ~0x00000004这三个字节,所以字节对齐实际上有以空间换时间的意思。写的时候具体怎么选代码,看个人了。
3.手动设置校准
何时需要手动设置校准:
在设计不同CPU下的通信协议时,比如共享一个结构的两台服务器之间的网络通信,需要手动设置对齐规则,保证两边的结构长度始终相同;
写硬件驱动时寄存器的结构;
有两种方法可以手动设置对齐:
在代码中添加预编译标识:
//用法如下
#pragma pack(n)//表示其后的代码按n字节对齐。
结构st3
{
char a;
int b;
};
#pragma pack()//根据N字节取消对齐是#pragma pack(n)的反向操作
//在这里,计算sizeof(st3)=5
以上两条线其实和开车差不多。当你走到某条路的时候,你发现一个限速60公里的标志。过了那条路,会有解除60公里限速的标志。
定义结构时:
//用法如下
结构bbb
{
char a;
int b;
}__attribute__((打包));//直接按照实际占用的字节对齐,实际上相当于按照1字节对齐。
//在这里,计算sizeof(st3)=5
4.结构比较法
您可以使用内存比较函数memcpy来比较结构,但是由于结构的对齐,可能会出现不一致的填充位。这时,你应该注意:
设置1字节对齐,使其没有空格;
提前初始化结构;
memcpy(char *dest,const char* src,int len);//头文件#includestring.h
关于C语言结构字节对齐的实现方法的这篇文章到此为止。有关C语言结构字节对齐的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望大家以后能多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。