文章目录
- 内存对齐
- 1.概述
- 2.如何进行内存对齐
- 3.位域对齐
- 大端存储与小端存储
- 1.基本概念
- 参考博客
😊点此到文末惊喜↩︎
内存对齐
1.概述
- 定义(什么是内存对齐)
- 编译器为程序中的每个数据单元安排在适当的位置上,从而减少CPU访存次数,提高数据读取效率的一种方式。
- 原因(为什么要内存对齐):
- 平台移植:不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
- 性能原因:为了访问未对齐的内存数据,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
- 缺点:内存对齐没有充分利用存储空间,但是
以空间换时间
对于常见业务场景会更高效 - 内存对齐示例
#include<stdio.h>
struct{
char y;// 一个字节
int x;// 四个字节
}Test;
int main()
{
printf("%d\n",sizeof(Test)); // 输出8不是5
return 0;
}
2.如何进行内存对齐
- 默认对齐系数:在每个特定平台的编译器可能不同,gcc中默认#pragma pack(4)
- 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。
- 使用伪指令#pragma pack (),取消自定义字节对齐方式。
- __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
- attribute((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。
- 基本类型的对齐值就是其sizeof值。常见数据类型:
数据类型 | char | short | int | float | long | double | longlong |
---|---|---|---|---|---|---|---|
大小 | 1Byte | 2Byte | 4Byte | 4Byte | 4Byte | 8Byte | 8Byte |
- 类、结构体和union的数据成员:第一个数据成员放在offset为0的地方,之后每个数据成员的对齐按照
#pragma pack指定值
和该数据成员sizeof值
中较小的值进行对齐。 - 类、结构体和union的整体对齐:整体最终字节数需要按照
#pragma pack指定值
和sizeof数据成员中的最大值
中较小的值的最小倍数值进行对齐
#include<stdio.h>
struct
{
int i; // 占前4个字节
char c1;// 两个char依次占后4个字节,实际只占两个字节
char c2;
}Test1;
struct{
char c1;// 对齐后占前4个字节,实际只占第一个字节
int i; // 占后4个字节
char c2;// 与第一个char类似,独自占4个字节
}Test2;
struct{
char c1;// 两个char依次占前4个字节,实际只占两个字节
char c2;
int i; // 占后4个字节
}Test3;
int main()
{
printf("%d\n",sizeof(Test1)); // 输出8
printf("%d\n",sizeof(Test2)); // 输出12
printf("%d\n",sizeof(Test3)); // 输出8
return 0;
}
3.位域对齐
- 定义:把一个字节中的“位”按照实际的需求分成不同的区域,表明每个区域位数、区域的域名,并允许程序按照域名进行操作
- 结构
struct 位域的结构体名
{
//位域列表
【类型说明符】 【位域名】:【位域的长度】;
}
- 规则
- 位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是不能超过8位二进位。
- 位域可以无位域名,此时只用于填充或调整位置,但无法使用。
- 各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同,向结构体成员中sizeof的最大的成员对齐。
大端存储与小端存储
1.基本概念
- 定义
- 大端存储和小端存储是两种计算机的存储模式
- 分离
- 小端存储:数据的高字节存储在高地址中,数据的低字节存储在低地址中
- 大端存储:数据的高字节存储在低地址中,数据的低字节存储在高地址中
// 大端存储
int a = 1;
// int在内存中占 4Byte;
// a在内存中的分布为 0x1 0x0 0x0 0x0;
// 从左到右内存地址降低,也就是高字节地址存放的是a的低字节数据
// 小端存储
int a = 1;
// int在内存中占 4Byte;
// a在内存中的分布为 0x0 0x0 0x0 0x1;
// 从左到右内存地址降低,也就是低字节地址存放的是a的低字节数据
🚩点此跳转到首行↩︎
参考博客
- 内存对齐的规则以及作用
- 采用内存对齐的方式存储数据的意义
- 一文轻松理解内存对齐
- C++ 位域
- C++ 位域
- C++ 位域
- C++ 位域
- C++ 位域