栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C/C++:内存对齐(struct/union/field)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C/C++:内存对齐(struct/union/field)

C/C++:内存对齐(struct/union/field) 原因

​ 字节对齐主要是为了提高内存的访问效率。

  • 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

  • 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

对齐原则
  • 首个成员在与结构体变量偏移量为0的地址处

  • 各成员变量在存放的时候根据在结构中出现的顺序依次申请空间

  • 变量对齐数 = Min(编译器默认对齐数,该成员大小)

  • 各成员变量对齐到自身对齐数的整数倍(嵌套结构体对齐到自身最大对齐数整数倍)

  • 结构体总大小为所有最大对齐数(包含嵌套结构体的成员对齐数)的整数倍

示例 1.不同顺序排列

​ S1大小:12字节(1+3 +4 + 1+3);

​ S2大小:8字节(1+1+2 + 4);

​ 粗体为对齐填充字节。

struct S1
{
    char c1;
    int i;
    char c2;
};
struct S2
{
 	char c2;
    char c1;
    int i;
};
2.包含数组

​ student大小:24(10+2+4+1+3+4)

​ char name[10] 的本质是 10 个 char 变量,所以就把它当成 10 个 char 变量看就行了;

​ 粗体为对齐填充字节。

struct student
{
	char name[10];
	int age;
	char sex;
	float score;
};
3.结构体嵌套

​ student大小:32(4+13+7+8)

​ st1大小:48(4+4+32+1+7)

struct student
{
	int num;
	char name[13];
	double gender;
};
struct st1
{
	int age;
	struct student s1;
	char sex;
};
4.联合体嵌套

​ 联合体对齐方式要适合其中所有的成员(整个大小为最大对齐数的整数倍)

​ MyUnion大小:16(13+3)

​ st1大小:32(4+4+16+1+7),union1应按成员最大字节对齐数(8)对齐,整个结构体为double倍数

union MyUnion
{
	int num;
	char name[13];
	double gender;
};
struct st1
{
	int age;
	union MyUnion union1;
	char sex;
};
pragma指令
  • 使用伪指令#pragma pack (n),C编译器将按照**min(n, sizeof(a))**个字节对齐(a为某类型变量,n= 1,2,4,8,16)。
  • 使用伪指令#pragma pack (),取消自定义字节对齐方式。
示例

1.S1大小:6(1+1+4)

​ S2大小:10(1+1+6+2),嵌套时按照min(2,sizeof(a))对齐

#pragma pack(2)
struct S1 {
	char a;
	long b;
};

struct S2 {
	char c;
	struct S1 d;
	char e;
};
#pragma pack()

2.S1大小:8(1+3+4)

​ S2大小:16(1+3+8+1+3),嵌套时按照min(8,sizeof(a))对齐

#pragma pack(8)
struct S1 {
	char a;
	long b;
};

struct S2 {
	char c;
	struct S1 d;
	char e;
};
#pragma pack()
位域

位域的声明和结构是类似的,有两个不同:

  • 位域的成员必须是 int、unsigned int、signed int、char等整形家族

  • 位域的成员名后边有一个冒号和一个数字

  • 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的

  • 一个位域必须存储在同一个字节中,不能跨两个字节

示例

​ 连续相同类型可使用位域来节省空间(S1)

​ 连续不同类型需按照对齐规则分配空间(S2)

​ 含位域的结构体嵌套对齐规则与普通嵌套相同(S3)

struct S1 {
	int i:8;
	int b:4;
	char a:3;
	double c;
};//16字节

struct S2 {
	int i:8;
	char a:3;
	int b : 4;
	double c;
};//24字节

struct S3 {
	char c;
	struct S2 d;
	char e;
};// 40字节

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1018827.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号