C语言之数据在内存中的存储

本文详细介绍了整数在内存中的存储方式,特别是补码的使用,以及大小端字节序的概念。通过实例和练习,探讨了如何判断机器字节序和处理浮点数的存储格式,依据IEEE754标准解析了浮点数在内存中的表示。
摘要由CSDN通过智能技术生成

整数在内存中的存储

在操作符的时候,我们就已经知道了,整数的二进制的表示方法有三种,就是原码,反码和补码,而整数的存储是在内存中存储它的补码,其中,对于有符号的整数,三种表⽰⽅法均有符号位和数值位两部分,符号位都是⽤0表⽰“正”,⽤1表⽰“负”,最⾼位的⼀位是被当做符号位,剩余的都是数值位。

正整数的原、反、补码都相同。负整数的三种表⽰⽅法各不相同。

对于负数而言,原码,反码,补码的转换:原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。补码:反码+1就得到补码。

大小端字节序和字节序的判断

我们调试如下的代码,得到结果

 那么什么是大小端呢?

实超过⼀个字节的数据在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分为⼤端字节序存储和⼩端字节序存储,下⾯是具体的概念:

⼤端(存储)模式:

是指数据的低位字节内容保存在内存的⾼地址处,⽽数据的⾼位字节内容,保存在内存的低地址处。⼩端(存储)模式:

是指数据的低位字节内容保存在内存的低地址处,⽽数据的⾼位字节内容,保存在内存的⾼地址处。

很好,现在我们一起来练习几道和大小端有关的习题吧

练习一

设计一个程序判断当前机器的字节序

int check_sys()
 {
    int i = 1;
    return (*(char *)&i);
 }

实际上,我们只需要放入1,然后看返回的第一个字节是1还是0就可以了

练习二

int main()
{    
    char a= -1;  
    signed char b=-1; 
    unsigned char c=-1;   
    printf("a=%d,b=%d,c=%d",a,b,c);  
    return 0;
}

这个输出的结果是什么?

a是-1,
//10000000000000000000000000000001
//11111111111111111111111111111110
//11111111111111111111111111111111
取出的是
//11111111
b是-1
//10000000000000000000000000000001
//11111111111111111111111111111111
//11111111
但是c要把最前面的1视作数字位
255

练习三

int main()
{   
    char a = -128;  
    printf("%u\n",a);    
    return 0;
}
a为-128
//10000000000000000000000010000000
//11111111111111111111111101111111
//11111111111111111111111110000000    补码
//10000000
这里认为a是无符号数
char所以要进行整型提升
//11111111111111111111111110000000 
int main()
{
    char a = 128;
    printf("%u\n",a);
    return 0;
}
//00000000000000000000000010000000
//10000000
整型提升
//11111111111111111111111110000000

练习四

int main()
{
    char a[1000];
    int i;
    for(i=0; i<1000; i++)
    {
        a[i] = -1-i;
    }
    printf("%d",strlen(a));
    return 0;
}

输出结果是什么?

char类型占据1个字节,它放入的内容是:

-1 -2 -3 -4 ... -127 -128 127 126 ... 4 3 2 1 0 -1 -2 ...

当为0是,相当于'\0',所以结果是255

练习五

//X86环境 ⼩端字节序
int main()
{    
    int a[4] = { 1, 2, 3, 4 };
    int *ptr1 = (int *)(&a + 1);
    int *ptr2 = (int *)((int)a + 1);
    printf("%x,%x", ptr1[-1], *ptr2);
    return 0;
}

取a的地址,+1在转换为int*的类型,指向4后面的位置

ptr1[-1]相当于*(ptr1 - 1),也就是4

将单独的a取出来实际是地址,现在视为一个数字,然后+1,就是地址真实+1,整数+1就是+1

然后我们输出红框的内容

浮点数在内存中的存储

常⻅的浮点数:3.14159、1E10等,浮点数家族包括:float,double,long double

浮点数表⽰的范围:float.h中定义

现在给出我们一个代码,请分析他的结果

int main()
{
    int n = 9;
    float *pFloat = (float *)&n;
    printf("n的值为:%d\n",n);
    printf("*pFloat的值为:%f\n",*pFloat); 
   *pFloat = 9.0;
    printf("num的值为:%d\n",n);
    printf("*pFloat的值为:%f\n",*pFloat);
    return 0;
}

输出的结果

我们发现,和我们想的并不同,因此我们知道了,整数和浮点数的存储是不同的

那么,浮点数在内存的存储是什么样的呢?

据国际标准IEEE(电⽓和电⼦⼯程协会)754,任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:

⽐如,2^10的E是 10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

E全为0时候, 这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,⽽是还 原为0.xxxxxx的⼩数。这样做是为了表⽰±0,以及接近于0的很⼩的数字。

E全为1时候,这时,如果有效数字M全为0,表⽰±⽆穷⼤(正负取决于符号位s);

感谢您的观看

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值