结构体内存对齐与联合体

news/2024/10/23 7:17:14/

目录

前言

结构体大小的计算

修改默认对齐数


前言

当我们了解结构体的声明,结构体的自引用,结构体变量的定义和初始化,如何计算结构体的大小呢?结构体类型的数据是在内存中如何存放的呢?这也是本文需要讨论的问题;

结构体大小的计算

//结构体声明
struct n
{char c1;int i;char c2;
};int main()
{struct n n1;//计算结构体的大小printf("%d\n", sizeof(n1));return 0;
}

char-字符类型-大小为1字节   int - 整型 - 大小为4字节,那么总大小是不是 1+4+1=6字节呢?

运行结果:

结果是12个字节,为什么?这就不得不涉及结构体内存对齐规则;

结构体内存对齐规则

1. 结构体第一个成员变量存放在与结构体变量偏移量为0的地址处

2. 其他成员变量要对齐到对齐数的整数倍的地址处;

    对齐数=编译器默认对齐数与成员变量大小的较小值;

  vs默认对齐数为8字节,linux环境没有默认对齐数,对齐数就是成员自身的大小

3. 结构体总大小为最大对齐数的整数倍

4. 对于嵌套结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍

接下来的讨论,全是在vs编译环境下,即默认对齐数为8; 假设创建结构体变量n1从0x0000ff40处开辟内存空间,示意图如下

 根据结构体对齐第一条规则:结构体第一个成员变量存放在与结构体变量偏移量为0的地址处;

  结构体成员变量c1就应该存放于偏移量为0的地址处,且占1byte; 如上图c1的位置;

根据结构体对齐第二条规则:其他成员变量要对齐到对齐数的整数倍的地址处;

1. 先计算对齐数 int在内存中占4个字节,默认对齐数为8个字节,对齐数为自身大小和默认对 齐数两者较小值 那么对齐数=4;结构体第二个成员变量就要对齐到4的整数倍,即偏移量等于4的位置,且占4byte,如上图i的位置;

2. 计算对齐数  har在内存中占1个字节,默认对齐数为8个字节,对齐数为自身大小和默认对 齐数两者较小值 那么对齐数=1;结构体第二个成员变量就要对齐到1的整数倍,即偏移量等于8的位置,且占1byte,如上图c2的位置;

 根据结构体对齐第三条规则:结构体总大小为最大对齐数的整数倍

 第一个对齐数=4,第二个对齐数=1 最大对齐数=4;结构体总大小=4*j (j=1,2,....)

已经用掉9个字节,下一个4的整数倍即偏移量为11的位置,12个字节;如上图绿色方框所示;

综上,已经分析出结果为12字节,那分析步骤是否如同我们如上所述,需要进行进一步验证

offsetof() - 宏 头文件 #include<stddef.h>

返回值为unsigned int ,第一个参数为结构体变量类型,第二个参数为成员变量名;

计算结构体成员相对于起始位置的偏移量

 验证如下:

# include <stddef.h>
struct n
{char c1;int i;char c2;
};
int main()
{printf("%u\n", offsetof(struct n, c1));printf("%u\n", offsetof(struct n, i));printf("%u\n", offsetof(struct n, c2));return 0;
}

运行结果:

 验证结果如上图所示,与示意图完美匹配,可以得出分析步骤完全正确;

当我们计算嵌套结构体的大小,如下计算n的大小,结果又是如何?

struct s
{double d;// 对齐数1=8;char c;//对齐数2=1;int i;//对齐数3=4;
};
//嵌套结构体最大对齐数=8字节;
//struct s的总大小经计算为16个字节struct n
{char c1;//对齐数4=1;struct s n1;double d;//对齐数5=8;
};
int main()
{printf("%d\n", sizeof(struct n));return 0;
}

根据结构体对齐的第四条规则:对于嵌套结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍;

不难得出结论,结果为32字节;

修改默认对齐数

使用 # pragma预处理指令来修改默认对齐数

# pragma pack(1)//设置默认对齐数为1;
struct n
{char c1;int i;char c2;
};
# pragma pack()//取消设置的默认对齐数,还原为默认;
int main()
{printf("%d\n", sizeof(struct n));return 0;
}

运行结果:

联合体

联合体定义

C语言中,变量的定义是分配存储空间的过程。一般的,每个变量都具有其独有的储存空间,那么是否可以在同一块存储空间储存不同的数据类型呢?

联合体也叫共用体,C语言中联合体的关键字是union,这种类型定义的变量也包含一些列的成员变量,特征是这些成员共用同一块内存空间;

//定义联合类型的声明
union 联合名
{成员列表;
};

验证过程:验证联合体成员是否共用同一块内存

union un
{char c;int i;
};
int main()
{union un u;printf("%p\n", &u);printf("%p\n", &(u.c));printf("%p\n", &(u.i));return 0;
}

运行结果:

 联合体大小的计算

联合体成员是共用同一块内存空间,一个联合变量的大小至少是最大成员的大小(因为联合体至少得有能力保存最大的成员变量);

//计算联合体的大小
union un
{char c;int i;
};
int main()
{union un u;printf("%d\n", sizeof(u));return 0;
}

运行结果:

但是联合体的大小一定是最大的成员的大小吗?

union un
{char arr[5];int i;
};
int main()
{union un u;printf("%d\n", sizeof(u));return 0;
}

运行结果:

 结果是8个字节,成员变量最大为int类型,只占4个字节,所以联合体变量的大小不一定是最大成员的大小;

联合体大小的计算

  • 联合体的大小至少是最大成员的大小;
  • 当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍处;

共用体从0偏移量处开始共用同一块内存空间,c为字符数组,数组成员为char,char占1个字节,vs默认对齐数为8,所以对齐数1=1;i为整型数据,占4个字节,vs默认对齐数为8所以对齐数2=8;所以最大对齐数=4;此时内存使用5个字节,但是要对齐到最大对齐数的整数倍的位置,即相对于起始位置的第8个字节处,即偏移量为7的位置,所以占用内存的大小为8字节;

 


http://www.ppmy.cn/news/429707.html

相关文章

电脑上可以连接网线可以上网,但是WiFi没有了

连接网线可以正常上网&#xff0c;拔掉网线、WiFi不会显示出来 1、首先【此电脑】左键打开 2、打开【计算机】 3、打开【设备管理器】》打开【网络适配器】 找到Itel(R) 把他删除进行 &#xff0c;最后进行更新安装即可

电脑连接WiFi正常,连接网线出现问题

1:电脑使用转接坞连接网线的时候&#xff0c;出现WiFi可以连接&#xff0c;网线连接上没有反应的情况&#xff0c; 1&#xff1a;在左面新建一个cmd快捷方式 2&#xff1a;右击管理员身份运行 3&#xff1a;输入netsh winsock reset 点击运行即可 4&#xff1a;重启电脑即可。…

怎么把学校计算机室的电脑连上网,笔记本电脑连不上校园网怎么办

在有些时候我们的笔记本电脑连不上校园网了&#xff0c;这该怎么办呢?那么下面就由学习啦小编来给你们说说笔记本电脑连不上校园网的解决方法吧&#xff0c;希望可以帮到你们哦! 笔记本电脑连不上校园网的解决方法&#xff1a; [检查网线] 一般网连不上就是出现像上述图片那样…

服务器不稳定拔掉网线重插上就能用,电脑只能上qq 其他程序都连不上网 拔网线重插就好了 什么原因啊...

满意答案 sbscfwww 2015.10.16 采纳率&#xff1a;58% 等级&#xff1a;8 已帮助&#xff1a;561人 在通过宽带路由器拨号上网的时候&#xff0c;我们有时候会遇到能使用QQ、但不能打开网页的奇怪现象&#xff0c;这种故障现象通常是由于域名解析不正确引起的&#xff0c;我…

计算机网线怎么连接另一台电脑,教你如何用一根网线将两台电脑直连

在办公过程中&#xff0c;我们经常需要在两台电脑之间传输文件&#xff0c;这时除了用U盘拷贝或者其他在线软件传输外&#xff0c;一些大型的数据我们还可以通过电脑直连的方法来传输。那么如何将两台电脑用网线直连呢&#xff1f;下面小编教下大家网线直连电脑传输数据的方法。…

电脑连不上网显示dns服务器不可用,电脑连不上网疑难解答显示DNS服务器可能不可用该怎么办...

在Internet上域名与IP地址之间是一对一(或者一对多)的&#xff0c;域名虽然便于人们记忆&#xff0c;但机器之间只能互相认识IP地址&#xff0c;它们之间的转换工作称为域名解析&#xff0c;域名解析需要由专门的域名解析服务器来完成&#xff0c;DNS就是进行域名解析的服务器。…

计算机应用网线接口亮红灯,网线插在电脑上网口灯不亮是为什么?

1、网线插在电脑上网口灯不亮&#xff0c;应该是接触不良。 2、如有你已经把上网的网线&#xff0c;插在了路由器的WAN口&#xff0c;但是WAN口指示灯仍然不亮。这时候&#xff0c;请检查以下几个方面的问题&#xff1a;检查网线是否插好&#xff0c;网线是否有问题。 3、如果确…

台式计算机网线插哪里,电脑主机网线插哪里?

问&#xff1a;电脑主机网线插在哪里&#xff1f; 答&#xff1a;这个需要根据你家的上网情况来决定&#xff0c;主要是看有没有用到路由器上网&#xff0c;下面进行详细说明。 1、如果你家里没有用路由器&#xff0c;那么电脑主机上的网线&#xff0c;需要插在猫的网口/LAN口。…