C++结构体struct的对齐规则及联合体union大小端

我们经常会遇到让我们计算某个结构体的所占字节这种问题,那么究竟怎么解决呢?

1.什么是结构体对齐?为什么要进行结构体的对齐?

虽然说内存是连续的,但是我们在里面放入数据时,不是一个一个依次紧密相连得放进去,而是得按照一定的规律,变量之间可能存在着间隙得放在内存中,这就是结构体对齐;因为某些硬件平台只能从规定的地址处取某些特定类型的数据,因此进行对齐后能够更加方便读取数据。

2.如何计算结构体的字节数?

我们只需要按照两个规则来计算即可:

规则1:每个结构体成员在结构体中的相对字节必须是其基本数据类型所占字节的整数倍

相对字节是指某个成员在整个结构体中的相对位置,即第几个字节的位置。注意基本数据类型只有 int、char、bool 、double、float、void、floatwchar_t(宽字符型)7种,对于非基本数据类型的特殊的结构体成员,例如说数组,它在整个结构体中的相对字节必须其中一个元素所占字节的整数倍;若是结构体的成员也是一个结构体,首先需要单独计算出嵌套的结构体的字节大小,它的相对字节必须是其所有成员中最长基本数据类型的整数倍。

规则2:整个结构体大小必须是其所有成员中最长基本数据类型的整数倍。

EX1:普通结构体

struct A1{
    int a;
    double b;
    char c[5];
    bool d;
};//sizeof(A1)=24

按照规则1就是 a的相对字节必须是4的整数倍,我们取0,a就占了0-3这一部分内存,b的相对字节必须是8的整数倍,我们取8,b就占了8-15这部分内存,c的相对字节必须是(char)1的整数倍,我们取16,c就占了16-20这部分内存,d的相对字节取21即可;再按照规则2,整个结构体的字节数必须是8的整数倍,所以sizeof(A1)=24。
整个成员内存分布可以看下面这张图:
在这里插入图片描述
EX2:结构体中的成员的顺序发生改变
结构体A2改变了A1中的成员顺序,总体所占字节也发生改变。

struct A2{
    bool d;
    double b;
    char c[5];
    int a;
};//sizeof(A2)=32

整个结构体的成员内存分布如下图所示
在这里插入图片描述
EX3:当结构体嵌套结构体

struct B{
    bool b;
    double d;
};//sizeof(B)=16
struct A3{
    int a;
    B b1;
    char c[3];
    
};//sizeof(A3)=32

比较方便计算出结构体B的总大小是16;对于结构体A, a的相对字节必须是4的整数倍,我们取0,a就占了0-3这一部分内存,把b1看做一个整体,所占字节是16,相对字节必须是double 的整数倍,因此b1就占了8-23这一部分内存,c相对字节是(char)1的整数倍,因此c占了24-26这部分内存;再根据规则2,整个结构体大小必须是double的整数倍,所以sizeof(A3)=32。
struct B:
在这里插入图片描述struct A3:
在这里插入图片描述

3.结构体和联合体的区别

3.1为什么要有联合体union?

我们联合体用关键字union修饰,理解为“共用体”更加贴切,它在任何时刻只有一个成员存在,所有成员共享一段内存,每个成员的相对字节都是0,更加节约内存。

3.2 如何计算联合体的大小

联合体只要能容纳其中最宽的成员即可,同时满足是其中基本数据类型的整数倍。看下面的例子

union U1{
    int a;
    char c[5]; 
};//sizeof(U1)=8(大于等于5且是4的倍数)
union U2{
    int a;
    char c[3]; 
};//sizeof(U2)=4(3和4中4大)
union U3{
    int a;
    char c[3];
    double d; 
};//sizeof(U3)=8 (4,3,8中8最大)
3.3联合体赋值

那我们在对联合体赋值的时候,每个成员都会是什么情况呢?试了下面的小例子,只给联合体中的int型数据赋值,那么没有赋值的字符数组会是什么情况呢?

#include <iostream>
#include <string>
using namespace std;
union U1{
    int a;
    char c[5]; 
};
int main(){
    U1 uu;
    uu.a=4;
    cout<<uu.a<<endl;   
}

显然会输出4,那么如果是

cout<<uu.c[0]<<endl;
cout<<uu.c[1]<<endl;
cout<<uu.c[2]<<endl;
cout<<uu.c[3]<<endl;
cout<<uu.c[4]<<endl;

会分别输出什么呢?我在VScode里面调试,有结果但是显示不出来,觉得很奇怪,换了种方式显示:

if(uu.c[0]==4)cout<<"yes0"<<endl;//输出yes0
if(uu.c[1]==0)cout<<"yes1"<<endl;//输出yes1
if(uu.c[2]==0)cout<<"yes2"<<endl;//输出yes2
if(uu.c[3]==0)cout<<"yes3"<<endl;//输出yes3
if(uu.c[4]==0)cout<<"yes4"<<endl;//输出yes4

结果显而易见,都会输出,那么内存中的情况也比较确定了,虽然没有给字符数组赋值,但是访问它时是不会报错的,而是会默认从联合体的对应位置去访问它。

3.3利用联合体判断大小端

首先介绍一下大小端的概念.
大端模式,是指数据的高字节位保存在内存的低地址中,而数据的低字节位保存在内存的高地址中。
小端模式,是指数据的高字节位保存在内存的高地址中,而数据的低字节位保存在内存的低地址中.

#include <iostream>
#include <string>
using namespace std;
union U1{
    int a;
    char c[2]; 
};
int main(){
    U1 uu;
    uu.a=1;
    if(&(uu.c[0])<&(uu.c[1]))cout<<"c[0]位于地地址,c[1]位于高地址。"<<endl;
    if(uu.c[0]==1)cout<<"小端"<<endl;
    else{
        cout<<"大端"<<endl;
    }
}

联合体的特点是所有成员相对地址都是0,上述代码首先将联合体uu的整型元素a赋值为1,因此内存中从高地址到低地址的比特数是00000000 00000000 00000000 00000001,后来又对c[0],c[1]赋值,首先判断出c[0]位于低地址,c[1]位于高地址,且c[0]对应的是00000001这部分内存,说明低地址的c[0]恰好是位于低字节的,因此是小段模式。
对应关系如图所示:由于字符变量c[0]=1,说明它对应的是内存的相对低字节,而c[1]=0,说明它对应的是内存的相对高字节;且c[0]位于低地址,c[1]位于高地址;而联合体的特性是所有的成员相对位置为0,因此是小端模式。在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 结构体struct)和联合体union)都是C语言中用于定义自定义数据类型的方式,它们的区别在于: 1. 结构体中的各个成员在内存中是分开存储的,而联合体中的各个成员在内存中是共用同一块空间的。 2. 结构体的大小至少是其各个成员大小之和,因为每个成员都需要占用一定的内存空间,而联合体的大小则是其最大成员的大小,因为联合体中只有一个成员会被使用,其它成员则会被浪费。 3. 结构体中的各个成员可以同时被访问和修改,而联合体中只有一个成员可以被访问和修改。 4. 结构体可以存储不同类型的成员,而联合体只能存储同一类型的成员。 总之,结构体适合用于存储多个不同类型的数据,而联合体适合用于存储多个相同类型的数据,且只有一个数据会被使用的情况。 ### 回答2: 结构体struct联合体union都是在C语言中用来组织多个不同类型的变量的一种方式。它们的区别在于变量的存储方式和内存占用。 结构体struct是一种可以存储不同类型的变量的自定义数据类型。它通过定义多个不同类型的变量,并将它们组合在一起,形成一个新的类型。结构体中的每个成员变量都使用独立的内存空间,大小根据成员变量的类型而定。结构体的成员可以同时存在于内存中,因此结构体可以存储和处理多个不同类型的数据。 联合体union也是一种可以存储不同类型的变量的自定义数据类型。它与结构体不同的是,联合体的成员变量共享同一块内存空间,也就是说,联合体的各个成员变量会在同一时间占用该内存空间。联合体的内存空间大小会根据最大的成员变量类型来决定。而为了节约内存空间,联合体只能同时存储和处理一个成员的数据。 结构体联合体的使用方式也不同。结构体通常用于组织多个相关的变量,可以同时访问和修改结构体的各个成员变量。而联合体通常用于存储不同类型的变量,根据不同的需求来访问和修改特定的成员变量。 综上所述,结构体联合体在存储方式、内存占用和使用方式上都有所不同,开发者要根据实际需求选择合适的数据类型。 ### 回答3: 结构体struct联合体union是C语言中的两种复合数据类型。 结构体struct允许将不同类型的变量(如整型、字符型、浮点型等)组合在一起,形成一个逻辑上的整体。它可以定义多个成员变量,每个成员变量可以有不同的数据类型和名称。通过使用结构体,可以更方便地管理和操作相关的数据。 而联合体union也是用来组合不同类型的变量,不同于结构体的是,联合体的所有成员变量都共享同一块内存空间。联合体的大小取决于成员变量中占用内存空间最大的数据类型。只能同时使用其中的一个成员变量,存取一个成员变量会覆盖之前存入的值。通过使用联合体,可以节省内存空间,但在数据使用时需要小心,确保不会出现意外的数据覆盖。 总结来说,结构体struct联合体union的区别是: 1. 结构体允许不同类型的成员变量,而联合体中的成员变量必须是相同的类型。 2. 结构体的成员变量占用不同的内存空间,联合体的成员变量共享同一块内存空间。 3. 结构体的大小等于所有成员变量所占内存空间的总和,联合体的大小等于最大的成员变量所占内存空间。 4. 结构体的所有成员变量可以同时使用,而联合体只能同时使用一个成员变量。 5. 结构体适用于存储和操作不同类型的相关数据,联合体适用于节省内存空间、只需存取其中一个成员变量的情况下。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值