教你5分钟轻松搞定内存字节对齐

时间:2022-05-03 08:35:10 

写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢?讲讲字节对齐吧.

/******************************分割线

如果体系结构是不对齐的,A中的成员将会一个挨一个存储,从而sizeof(a)为11。显然对齐更浪费了空间。那么为什么要使用对齐呢?

体系结构的对齐和不对齐,是在时间和空间上的一个权衡。对齐节省了时间。假设一个体系结构的字长为w,那么它同时就假设了在这种体系结构上对宽度为w的数据的处理最频繁也是最重要的。它的设计也是从优先提高对w位数据操作的效率来考虑的。比如说读写时.............此处省略50万字

*******************************************************/

上面是你随便google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则:(在没有#pragma pack宏的情况下,务必看完最后一行)

1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。

2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)

3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐.

等你看完此3条原则,2分钟已经过去,抓紧时间,实战3分钟:


typedef struct bb
{
 int id;             //[0]....[3]
 double weight;      //[8].....[15]原则1
 float height;      //[16]..[19],总长要为8的整数倍,补齐[20]...[23]原则3
}BB;

typedef struct aa
{
 char name[2];     //[0],[1]
 int  id;         //[4]...[7]原则1

 double score;     //[8]....[15]
 short grade;    //[16],[17]
 BB b;             //[24]......[47]原则2
}AA;

int main()
{
  AA a;
  cout<<sizeof(a)<<" "<<sizeof(BB)<<endl;
  return 0;
}

结果是

48 24
ok,上面的全看明白了,内存对齐基本过关.

再讲讲#pragma pack().

在代码前加一句#pragma pack(1),你会很高兴的发现,上面的代码输出为

32 16
bb是4+8+4=16,aa是2+4+8+2+16=32;

这不是理想中的没有内存对齐的世界吗.没错,#pragma pack(1),告诉编译器,所有的对齐都按照1的整数倍对齐,换句话说就是没有对齐规则.

明白了不?

那#pragma pack(2)的结果又是多少呢?对不起,5分钟到了,自己去测试吧.

ps:Vc,Vs等编译器默认是#pragma pack(8),所以测试我们的规则会正常;注意gcc默认是#pragma pack(4),并且gcc只支持1,2,4对齐。套用三原则里计算的对齐值是不能大于#pragma pack指定的n值。

标签:字节对齐
0
投稿

猜你喜欢

  • C#中使用强制类型实现字符串和ASCII码之间的转换

    2022-05-15 14:57:48
  • Java泛型机制与反射原理相关知识总结

    2023-11-11 06:02:15
  • SpringBoot + validation 接口参数校验的思路详解

    2023-10-09 11:59:12
  • Java实现去除文档阴影的示例代码

    2023-08-31 11:45:48
  • javac -encoding 用法详解

    2022-06-28 08:58:08
  • 如何用C#找出数组中只出现了一次的数字

    2021-06-15 15:42:56
  • javaweb项目如何实现手机短信登录

    2021-05-27 03:09:25
  • Java 数据结构与算法系列精讲之哈希算法实现

    2022-01-10 23:56:07
  • C#实现终止正在执行的线程

    2022-05-06 22:34:22
  • JNDI简介_动力节点Java学院整理

    2023-04-20 03:19:23
  • 使用Maven配置Spring的方法步骤

    2023-02-05 18:37:46
  • C#使用Resources资源文件

    2023-07-04 08:42:48
  • C#之继承实现

    2023-04-10 16:51:41
  • Android仿开心消消乐大树星星无限循环效果

    2021-10-04 07:19:06
  • 关于各种排列组合java算法实现方法

    2023-11-15 05:46:55
  • C#中#define后面只加一个参数的解释

    2022-09-06 07:23:55
  • c#得到本月有几周和这几周的起止时间示例代码

    2022-11-01 15:20:34
  • c++中的malloc底层实现代码

    2023-11-02 19:49:18
  • java中Locks的使用详解

    2023-11-29 00:18:38
  • 浅谈Mybatis通用Mapper使用方法

    2023-02-15 17:46:52
  • asp之家 软件编程 m.aspxhome.com