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

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

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

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

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

文章目录
    • 1.什么是结构体对齐?为什么要进行结构体的对齐?
    • 2.如何计算结构体的字节数?
      • 规则1:每个结构体成员在结构体中的相对字节必须是其基本数据类型所占字节的整数倍
      • 规则2:整个结构体大小必须是其所有成员中最长基本数据类型的整数倍。
      • 3.结构体和联合体的区别
        • 3.1为什么要有联合体union?
        • 3.2 如何计算联合体的大小
        • 3.3联合体赋值
        • 3.3利用联合体判断大小端

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 
#include 
using namespace std;
union U1{
    int a;
    char c[5]; 
};
int main(){
    U1 uu;
    uu.a=4;
    cout< 

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

cout< 

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

if(uu.c[0]==4)cout<<"yes0"< 

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

3.3利用联合体判断大小端

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

#include 
#include 
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]位于高地址。"< 

对应关系如图所示:由于字符变量c[0]=1,说明它对应的是内存的相对低字节,而c[1]=0,说明它对应的是内存的相对高字节;且c[0]位于低地址,c[1]位于高地址;而联合体的特性是所有的成员相对位置为0,因此是小端模式。

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

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

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