字节 对齐 方法

3 篇文章 0 订阅
1 篇文章 0 订阅

字节对齐

引言

  字节对齐,由空间换取时间的产物之一。是指在变量进行访问时,会在不同类型的变量之间放置一段间隔空间,以此对数据进行所谓的“对齐”操作,从而达到提升程序访问数据的速度、节省时间的目的。主要用在结构体中,因此,大部分结构体会因变量申明的顺序不同或者是平台不同将产生不同的空间大小,如此如何正确计算出一个结构体空间的大小便成为了一件令人头疼的事情,以下我们将详细介绍以下不同的情况下,对字节对齐的理解及空间大小的计算。

背景

  现代计算机中内存空间都是按照BYTE划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开发,但是实际中却是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是一个接着一个紧挨着放,这就存在所谓的对其。

计算

  关于字节对齐的计算我们主要要把握住以下四点基本操作规则:
  1.基本数据类型的自身对其值
  2.程序的指定对齐值
  3.自定义类型的自身对齐值
  4.自定义类型的有效对齐值
  下面以一些具体的案例对这些原则的运用进行论述

规则一、基本数据类型的自身对其值

  我们都知道每一种类型的数据都有其自身的所占空间大小,
  char:1字节;
  short:2字节
  int :4字节
  float: 4字节
  double:8字节
  在使用这一原则时,我们遵循向下对齐的方法,即先声明的数据其所占总空间要是下面一个数据类型的整数倍。如

typedef struct Test//首先考虑自身的对齐
{
	char a;     //1字节
	short b;    //2字节
	int c;      //4字节
	long d;     //8字节
}Test;

  我们可以知道,其类型分别对应着1/2/4/8字节,而这远远不是最后的结果,但可以肯定的是结果一定比15要大,那该如何计算呢?
按照我们基本数据类型的自身对其的原则,上面的空间要是下面类型空间的整数倍,则

typedef struct Test//首先考虑自身的对齐
{
	char a;     //1字节+1字节
	short b;    //2字节    .....一共4字节
	int c;      //4字节    .....一共8字节
	long d;     //8字节    .....一共16字节
}Test;

  所以答案是16字节,但是在这里并不是处处都适用的,其需要结合第三条规则一同使用,后文将进行介绍。注

规则二、程序的指定对齐值

  除了数据类型自己的默认对齐之外,我们也可以对其进行自定义对齐大小,即使用#pragma pack(value),指定对齐值为value。这样我们在计算空间时不用再是下一个数据类型的整数倍,只需是value的整数倍即可(存在例外情况,结合规则四)
先看如下代码:

#pragma pack (2)
typedef struct ASS
{
	char a;     //1字节+1字节(与2对齐而不是与4对齐) .....一共2字节
	int b;    //4字节    .....一共6字节
	double c;      //8字节         .....一共14字节
	char d;     //1字节+1字节         .....一共16字节
}ASS;

  所以通过以上对齐统统与2相比较,结果为16字节

规则三、自定义类型的自身对齐值

  在除了以上两个结构体中的基本对齐之外,往往我们计算出来的值与最后的结果仍有偏差,这是因为我们还要考虑结构体自身的对齐。也叫自定义类型的自身对齐值,即结构体或类的成员中自身对齐值最大的值,也就是结构体中数据类型最大对齐的整数倍,
例如:

typedef struct ASS
{
	char a;     //1字节
	char b;    //1字节+2字节     .....一共4字节
	int c;      //4字节         .....一共8字节
	char d;     //1字节         .....一共9字节
}ASS;

  它的结果远远不是我们计算触电9那么简单,其空间大小的结果却是12,是因为它要与(int)对齐,所以在9的基础上在加上3个字节。

规则四、自定义类型的有效对齐值

  规则四是在计算对齐空间的最核心的部分,在#pragma pack(value)自定义了对齐大小之后,我们所要判断真实对齐大小则需找到其有效值,在这里我们记住一点,取二者中最小的那一个值进行对齐(一旦出现#pragma pack(value)之后,所有的对齐判断都必须考虑有效对齐值,包括规则三中自定义类型的自身对齐值亦是取二者当中最小的那个)
如以下程序:

#pragma pack(2)
typedef struct ASS
{
	char a;     //1字节+1字节(在2与4中取2对齐) .....一共2字节
	int b;    //4字节 (在2与8中取2对齐)   .....一共6字节
	double c;   //8字节       .....一共14字节
	short d;     //2字节              .....一共16字节
	int f;		//4字节      .......一共20字节(是2的倍数不用往8的倍数靠)
}ASS

  所以结果是20,char与2对齐,所以后面补1个字节的空间,与int一共6个字节是2的倍数,再加上下边double一共14个字节,是2的倍数,加上short的2个字节,一共16个字节,最后加上int的4字节一共是20个字节,在这里我们对自定义类型的自身对齐值是8,但是我们取8和2中最小的那个因此20是2的倍数,不需再补,结果是20.

  在字节对齐时牢记这四个规则,按步执行便可正确计算出所需结果了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值