【C上分之路】第九篇:联合体的内存分布、大小端判断

冲

Union

联合体是一种数据类型,表示在同一个内存空间中存储不同的数据类型,联合体有时也被称为共用体,联合体只能存储一个值

联合体主要设计用于一种表以存储无规律、事先也不知道的混合类型

Union定义格式

1、先定义、后创建变量

union test{
    int num;
    short sh;
    char ch;
};
union test t1,t2,t3;

2、定义的同时创建变量

union test{
    int num;
    short sh;
    char ch;
}t1,t2,t3;

Union初始化

1、初始化联合体第一个元素

#include <stdio.h>
union test{
    int num;
    short sh;
    char ch;
};
int main()
{
    union test t1 = {88};
    printf("t1.num=%d\n",t1.num);
    printf("t1.sh=%d\n",t1.sh);
    printf("t1.ch=%d\n",t1.ch);
    return 0;
}

2、联合体指定初始化

#include <stdio.h>
union test{
    int num;
    short sh;
    char ch;
};
int main()
{
    union test t1 = {.ch = 'A'};
    printf("t1.num=%d\n",t1.num);
    printf("t1.sh=%d\n",t1.sh);
    printf("t1.ch=%d\n",t1.ch);
    return 0;
}

3、联合体初始化同类别的联合

#include <stdio.h>
union test{
    int num;
    short sh;
    char ch;
};
int main()
{
    union test t2;
    t2.sh = 20;
    union test t1 = t2;
    printf("t1.num=%d\n",t1.num);
    printf("t1.sh=%d\n",t1.sh);
    printf("t1.ch=%d\n",t1.ch);
    return 0;
}

Union与Struct的区别

结构体的各个成员占用不同的内存,互相之间没有影响;联合体的所有成员都占用同一块内存,修改一个成员会影响其他成员

结构体占用的内存大于等于所有成员占用的内存的总和;联合体占用的内存等于其最大成员所占用的内存,联合体采用内存覆盖的技术,同一时刻只能保存一个成员的值,对联合体新成员赋值会将原来的值覆盖掉

Union的内存分布

union test{
    unsigned int num;
    short sh;
    char ch;
};

上面三种初始化例子都是对联合体的单个成员进行单一赋值,联合体成员都是占用同一块内存,所以联合体每个成员输出的都是同一个值

1、先赋值char,再赋值short

#include <stdio.h>
union test{
    unsigned int num;
    short sh;
    char ch;
};
int main()            
{
    union test t;           //1000    ---->         11 1110 1000
    //t.sh = 1000;            //11101000    ----->   10010111   10011000  =- (2^4+2^3)  =- (16+8) = -24
    t.ch = 'a'; 
    t.sh = 1000;               // 1100001              1101100001 
    printf("t.num=%d\n",t.num);
    printf("t.sh=%d\n",t.sh);
    printf("t.ch=%d\n",t.ch);
    return 0;
}

联合体内存分布1-1-1

联合体内存分布1-2

从运行结果可以看到联合体t1的三个成员num、sh、ch分别为1000、1000、-24

首先联合体t1三个成员都占用4个字节的内存空间,首先对char类型成员进行赋值:ch=‘a’,此时联合体三个成员输出都为字符a的编码值97,然后对short类型成员进行赋值:sh=1000;因为联合体同一时刻只能保存一个值,所以1000会将之前的字符编码值覆盖掉,1000的二进制数表示为:0000 0011 1110 1000;故此时联合体的num、sh成员输出为1000,而ch成员只占用一个字节,所以此时ch表示的是sh成员的一个字节内存上的二进制数,即:1110 1000,然后负数符号位不变,其余取反加1得到补码为:1001 1000,为-24

2、先赋值short、在赋值char

#include <stdio.h>
union test{
    unsigned int num;
    short sh;
    char ch;
};
int main()            
{
    union test t;           //1000    ---->         11 1110 1000
    t.sh = 1000;            //11101000    ----->   10010111   10011000  =- (2^4+2^3)  =- (16+8) = -24
    //t.ch = 'a';
    printf("t.num=%d\n",t.num);
    printf("t.sh=%d\n",t.sh);
    printf("t.ch=%d\n",t.ch);
    printf("*************\n");
    t.ch = 'a';              // 1100001              1101100001 
    printf("t.num=%d\n",t.num);
    printf("t.sh=%d\n",t.sh);
    printf("t.ch=%d\n",t.ch);
    return 0;
}

联合体内存分布2

联合体内存分布2-2

从运行结果可以看到联合体t1的三个成员num、sh、ch分别为865、865、97

先赋值short类型:sh=1000,同上联合体三个成员输出分别为:1000、1000、-24

此时联合体所占用的四个字节的二进制数为0000 0011 1110 1000;然后赋值char类型:ch = ‘a’,此时ch占用第一个字节的二进制数会覆盖了之前sh在第一个字节所表示的二进制数,此时联合体占用的四个字节上的二进制数为0000 0011 0110 0001,所以此时输出联合体的ch成员时不会还是为字符编码值97,但是此时二进制数0000 0011 0110 0001转换成十进制为865

大端小端

计算通常采用的字节存储方式是两种:Big-Endian和Litter-Endian

字节序?

字节序:就是字节的顺序,大于一个字节类型的数据在内存中的存放顺序

Big-Endian:大端是高位字节先存储(低地址)

Litte-Endian:小端是低位字节先存储(低地址)

网络字节序:TCP/IP协议各层将字节序定义为Big-Endian,因此TCP/IP中使用的字节序被称之为网络字节序,也就是大端

操作系统一般都是小端

联合体高低字节

高低字节:不论什么进制,靠近左边的称之为高位字节,靠近右边为低位字节

**就拿 0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78。**

Big-Endian:最不重要字节(LSB)存放在最低端的地址上

Litter-Endian:最不重要字节(LSB)存放在最低端的地址上

判断大小端

#include <stdio.h>
union endian
{
    int a;
    char ch;
};
int main()
{
    union endian value;
    value.a = 0x1234;
    if (value.ch == 0x12)
        printf("big endian\n");
    else if (value.ch == 0x34)
        printf("little endian\n");
}

联合体大小端

总结

联合体是一种数据类型,表示在同一个内存空间中存储不同的数据类型,只能存储一个值,同一时刻只能保存一个成员的值,对联合体新成员赋值会将原来的值覆盖掉

赶紧学习起来吧!我是一个正在努力找回自我的人,希望能和一起学习的人成长,有错误的地方请各位大佬帮忙指正,如果觉得有帮助就点个赞当作对我的一个小肯定❤,peace&love

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值