C语言字节对齐详解

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/tomatolee221/article/details/89473834

什么是字节对齐?
字节(Byte)是计算机信息技术用于计量存储容量和传输容量的一种计量单位,一个字节等于8位二进制数,在UTF-8编码中,一个英文字符等于一个字节。字节按照一定规则在空间上排列就是字节对齐。C / C ++中的每种数据类型都有对齐要求(事实上它是由处理器架构强制实现的,而不是由语言强制实施)。处理器将具有与数据总线大小相同的处理字长。在32位机器上 ,处理字大小为4个字节。

为什么要字节对齐?(在32位机器中)
事实上,存储器是字节可寻址的并且顺序排列。如果存储器被安排为一个字节宽度的单个存储体,则处理器需要发出4个存储器读取周期来获取整数。但是这样大大的浪费了处理器的资源,效率低下。其实在一个存储周期中读取所有4个字节的整数这样效率更高,为了获取这样的优势,存储器将被安排为4组一列,如下图所示:
在这里插入图片描述

其中,如果整数分配的地址不是4的倍数,则它跨越两行的存储区,如下图所示,这样整数就需要俩个存储器读取周期来获取整数数据。
在这里插入图片描述
还有一个原因:
平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址 处取某些特定类型的数据,否则抛出硬件异常

在32位机器上,各个数据类型的自然对齐字节数:

类型 32位机器
char 1
short 2
int 4
float 4
double 8
long 4
long long 8

从代码角度验证字节对齐

在C语言中结构体属于自定制数据类型,那么结构体的大小怎么算呢?我们来详细看一下。

//以下运行的结果sizeof(St) = 4字节
typedef struct St{
	char a;
	char b;
	short c;
}	St;

//以下运行的结果sizeof(St1) = 6字节
typedef struct St1{
	char a;
	short c;
	char b;
}	St1;

//以下运行结果sizeof(St2) = 8字节
typedef struct St2{
	char a;
	char b;
	int c;
}	St2;

//一下运行的结果sizeof(St3) = 12字节
typedef struct St3{
	char a;
	int c;
	char b;
}	St3;

从内存分布角度分析字节对齐:(这里拿St2和St3进行分析)
在这里插入图片描述

在这里插入图片描述
红色为所填充的对齐字节数;

最后再来练习俩个例子:

//程序运行sizeof(St4) = 20字节
typedef struct St4{
	char a;
	int c;
	char arr[10];
}	St4;

因为最大对齐变量为int(4),则char a后面填充了3字节,char arr[10]后面填充了2字节,所有加起来正好是20位int(4)的整数倍。

//程序运行sizeof(St3) = 32字节
typedef struct St3{
	char d;
	struct St8{
		char a;
		int b;
		char c;
	};
	double e;
	char f;
}	St3;

因为最大对齐数为double(8),St8对齐数为4,计算得St8位12字节,不是8的倍数,char d自动填充3字节,前面就为16字节,double e为8字节,char f自动在后边填充7字节,总共为32字节。

从运行的结果以及内存分布来看,得出结论:

  1. 结构体定义时,变量成员的顺序会影响结构体的大小
  2. 成员变量在内存中的排列是有间隔的不是紧密排列
  3. 结构体最大字节数为每个结构体中最大变量的整数倍(例如以上的例子中,只要为int的整数倍就好,其他的short,double也是类似的)
  4. 如果有相同的变量,可以放在一起,可以减小结构体的空间
  5. 编译器对于内存对齐方式可以选择,vs默认8,Linux默认4
  6. 字节对齐是在用空间换取时间(速度)

自定义对齐数:

在程序运行代码前加上#pragma pack(1)设置为以1字节对齐,那么以下字节数为:

//程序运行sizeof(St3) = 16字节
typedef struct St3{
	char d;
	struct St8{
		char a;
		int b;
		char c;
	};
	double e;
	char f;
}	St3;

要取消改为默认则只需添加#pragma pack()就好;

//占16字节
#pragma pack(1)
typedef struct St3{
	char d;
	struct St8{
		char a;
		int b;
		char c;
	};
	double e;
	char f;
}	St3;

//占12字节
#pragma pack()
typedef struct St2{
	char a;
	int b;
	char c;
}	St2;

猜你喜欢

转载自blog.csdn.net/tomatolee221/article/details/89473834
今日推荐