关于共用体赋值占用内存大小的问题(包含了小数如何转换并存储在内存)

之前只写过如何来看共用体的大小:成员里面最宽基本成员大小。

再来引入一个问题:共用体内部成员会不会填充字节?

我们这样来进行思考,按照结构体的原则来分析共用体大小:共用体大家共用一片内存,也就是每一个成员的的地址偏移量是0,由于当前数据偏移量必须是当前成员整数倍,那么这一条基本可以不管,因为偏移量是0。那么数据总大小必须是最宽基本成员的整数倍,那我们现在必须明白一个问题就是, 共用体取的是最大的成员大小, 而不是最宽的,我的意思是里面可能有数组。 

下面来分析一下两个共用体的大小:

共用体1:

共用体2: 

             注意共用体2这个位置是进行了字节填充的。                                                                                                                                               

下面说一下赋值的问题:只会对其中某一个成员进行赋值。也就是只有赋值的这个成员会存在内存里面,然后这片内存会按照它的相应类型进行解析。其他成员共用这片内存,其他成员在解析的时候就是按照它自己相应的类型进行解析的。

再次之前补充一个转换知识:小数如何转换并且存储在内存当中。

上面是double八个字节的表示方法。我简单说一下四个字节的表示方法,也就是单精度浮点数:符号位(1位),指数位(8位)和尾数位(23位)。另外说一点,小数部分是0.2,不断乘以2取整数部分,直到小数部分为0或者达到所需精度。对于单精度浮点数,指数位是8位,偏移量是127,也就是指数要+127

下面做一下两者的对比

从上面也可以看出 ,双精度能保留更多尾数位,所以损伤的精度也较小。                                       

然后之前也讲过数据的存放方式,是按照小端的方式来存放数据的,也就是说,低字节存放在低地址位。下面对共用体内存做一个验证。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

//内部无字节填充
union data {
    uint32_t i;//4个字节
    double f;//8个字节
    uint8_t arr[4];//4个字节
};//这里大小是8个字节


/**
 *测试得到数据是3.2,转成二进制就是 
 首先分析一下如何转换的:
 3.2的完整二进制表示:11.00110011...2这是一个无限循环
规范科学计数法,并且把小数点进行移位:1.1001100110011.....2 x  2^1 (这里指数是1,存的时候偏移了1023)
所以实际指数位是:1 + 1023 = 1024(二进制表示就是10000000000)
然后按照小数点在内存中的分布是:符号位:1位 指数位:11位 尾数位:52位
所以它的二进制组成就是:符号位 0 指数部分 10000000000 尾数 1001无限循环到合适的精度
所以它的完整二进制就是:0 10000000000 1001100110011001100110011001100110011001100110011010
八个字节的内存布局就是:(这里考虑按照小端存放)
    地址   | 二进制
    0x00 | 10011010
    0x01 | 10011001
    0x02 | 10011001
    0x03 | 10011001
    0x04 | 10011001
    0x05 | 10011001
    0x06 | 00001001
    0x07 | 01000000
 */
 
int main()
{
    //先拿data这个共用体进行测试
    union data dt;
    dt.f = 3.2;
    
    printf("%.1f\n",dt.f);//正常全部获取共用体data全部字节,打印3.2
    //i只获取前四个字节,前四个字节的二进制数据,注意数据是按照小段模式存放的
    //换句话说这里拿出前四个字节就是10011001100110011001100110011010变成十进制就是2576980378
    printf("%u\n", dt.i);//2576980378
    //下面我们在来测试一下arr这个数组打印情况
    //这个也是获取前四个字节
    //arr[0]对应就是10011010->154 arr[1]对应就是10011001->153
    printf("%u %u\n", dt.arr[0], dt.arr[1]);//154 153


    return 0;
}

      运行结果:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值