浅学C语言-精准分析各种数据在内存中的存储篇

剖析各种数据类型在内存中是怎样储存的?


家人们集美们,就是说咱们接下来会有一个大动作,那咱们先来浅读一下吧
推荐使用电脑端观看!手机端观感很差!


学习重点:

  1. 各种数据类型的具体介绍
  2. 整数在内存中存储:原码,反码,补码
  3. 大小端字节序
  4. 浮点数在内存中的存储

数据类型的介绍

  1. 各种数据类型

    • char //字符数据类型

      char类型其实是属于整型家族中的,因为char类型实际存储的是ASCII码,ASCII为整数,所以char类型属于整形家族

    • short //短整型

    • int //整形

      在早期的16位机器上是2个字节,在现在的32、64位机器上是4字节

    • long //长整型

      C语言规定,sizeof(long)>=sizeof(int)

    • long long //更长的整形

    • float //单精度浮点数

    • double //双精度浮点数

    • _Bool //布尔类型:专门用来判断真假的

      但其实在C语言中,对于布尔变量用的不多,其实本质就是把int进行了重命名

      使用布尔类型要引用头文件:#include<stdbool.h>

      举个例子:

      #include <stdbool.h>
      #include<stdio.h>
      
      int main()
      {
      	_Bool flag = true;
      	if (flag)//flag为真时打印
      	{
      		printf("hehe\n");
      	}
      	return 0;
      }
      
      
  2. 类型的基本归类

    1. 整形家族:

      char

      • unsigned char

      • signed char

      char到底是unsigned char还是signed char是取决于编译器的,常见的编译器中char是signed

      char的

      short

      • unsigned short
      • signed short

      short是signed short

      int

      • unsigned int
      • signed int

      long

      • unsigned int
      • signed int

      long是signed long

    注:无符号数不应该用%d打印,应该用==%u==打印

    举个例子:

    #include<stdio.h>
    
    int main()
    {
    	//正数:打印用%d %u都没问题 
    	unsigned int num = 10;
    	printf("%d\n", num);
    	printf("%u\n", num);
    
    	//负数:打印用%d没问题,用%u会错误
    	unsigned int n = -10;
    	printf("%d\n", n);
    	printf("%u\n", n);
    	return 0;
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rCUkyDaK-1644641270194)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644587042227.png)]

    1. 浮点数家族:

      • float 单精度浮点数 4个字节
      • double 双精度浮点数 8个字节
    2. 构造类型(自定义类型)

      • 数组类型

        数组的类型:去掉数组名(可以通过更改数据类型,元素个数来改变数据类型)

      • 结构体类型 struct

      • 枚举类型 enum

      • 联合类型 union

    3. 指针类型

      • int* pi;

      • char* pc;

      • float* pf;

      • void* pv;

        空类型:void表示空类型,即无类型

        举个例子:

        //返回值类型为空 参数为空 指针类型为void*
        void test(void)
        {
        	void* p;
        }
        
        int main()
        {
        	test();
        	return 0;
        }
        
        

整数在内存中的存储

  1. 原码 反码 补码

    1. 原码 反码 补码都由符号位 数值位组成

      • 符号位:0正1负

      • 数值位:

        • 原码:直接将二进制按照正负数的形式翻译成二进制就可以。
        • 反码:将原码的符号位不变,其他位依次按位取反就可以得到了。
        • 补码:反码+1就得到补码。
      • 正数的原反补相同,负数的原反补需要计算

      • 在内存中其实存放的是补码
        原因:在这里插入图片描述

      接下来,我们讲解几个例子

      例子1:内存在VS2019怎么进行查看

      1. 按下键盘上的F10开始调试(部分笔记本用户需要按住Fn+F10,不过你也可以把Fn键锁上,方法:Fn+Esc,这时候你的Fn键就被锁了,直接按F10开始调试)

      2. 调试->窗口->内存->随便选择一个

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kg7UdcNb-1644641270197)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644587952027.png)]

      1. 输入&a,然后回车

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7K97e1oK-1644641270199)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644588033651.png)]

      1. 我们需要关注的区域

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V3SxPOEM-1644641270200)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644588242558.png)]

      例子2 :15与-15的原码 反码 补码

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gDdAUiIT-1644641270201)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644588551309.png)]

      例子3 :10和-10的原码 反码 补码

          [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LGexn19n-1644641270203)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644588674035.png)]

    2. 大小端字节序

      1. 什么是大端小端:

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2KxTtiwR-1644641270204)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644589095083.png)]

      2. 举例:

        int a = 1;
        ->0x 00 00 00 01
        

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YTI40tNM-1644641270206)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644589200793.png)]

      3. 一道笔试题:来自百度2015年系统工程师笔试题

        请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。

        大端字节序存储: 当一个数据的低字节的数据存放在高地址处,高字节序的内容放在了低地址处,这种存储方式就是大端字节序存储

        小端字节序存储:当一个数据的低字节的数据存放在低地址处。高字节序的内容,放在了高地址处,这种存储方式就是小端字节序存储

        代码实现:

        思路:

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HOpLyIAa-1644641270207)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644589823802.png)]

        #include<stdio.h>
        
        int check_sys()
        {
        	int a = 1;
        	char *p = (char*)&a;//char类型的指针一次能访问一个字节,访问一次就是访问了第一个字节的内容
        	if (1 == *p)
        		return 1;//小端
        	else
        		return 0;//大端
        }
        
        int check_sys()
        {
        	int a = 1;
        	char* p = (char*)&a;
        	return *p;
        }
        
        int check_sys()
        {
        	int a = 1;
        	return *(char*)&a;//強转之后解引用,解引用访问一个字节
        }
        
        
        int main()
        {
        	int ret = check_sys();//返回1是小端,返回是大端
        	if (1 == ret)
        	{
        		printf("小端\n");
        	}
        	else
        	{
        		printf("大端\n");
        	}
        	return 0;
        }
        
    3. 八道练习题,让你直接起飞,芜湖~

      1. 下面程序输出什么?

        #include <stdio.h>
        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;
        }
        

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7XymJ2Gg-1644641270207)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644640861574.png)]

      2. 下面程序输出什么?

        #include <stdio.h>
        int main()
        {
        	char a = -128;
        	printf("%u\n", a);
        	return 0;
        }
        

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dcfVa3ug-1644641270209)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644640911849.png)]

      3. 下面程序输出什么?

        #include <stdio.h>
        int main()
        {
          char a = 128;
          printf("%u\n",a);
          return 0;
        }
        

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vKwoqs1g-1644641270210)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644640945011.png)]

      4. 下面程序输出什么?

        #include <stdio.h>
        int main()
        {
        	int i = -20;
        	unsigned  int  j = 10;
        	printf("%d\n", i + j);
        	//按照补码的形式进行运算,最后格式化成为有符号整数
        	return 0;
        }
        

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DyqHZtsn-1644641270212)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644640999042.png)]

      5. 下面程序输出什么?

        #include <stdio.h>
        int main()
        {
        	unsigned int i;
        	for (i = 9; i >= 0; i--)
        	{
        		printf("%u\n", i);
        	}
        	return 0;
        }
        

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OYsQy07F-1644641270214)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644641032878.png)]

      6. 下面程序输出什么?

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

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NytmVeOg-1644641270216)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644641065527.png)]

      7. 下面程序输出什么?

        #include <stdio.h>
        unsigned char i = 0;
        int main()
        {
        	for (i = 0; i <= 255; i++)
        	{
        		printf("hello world\n");
        	}
        	return 0;
        }
        

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pjSakKCZ-1644641270218)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644641100369.png)]

      8. 下面程序输出什么?

        #include <stdio.h>
        int main()
        {
        	unsigned char a = 200;
        	unsigned char b = 100;
        	unsigned char c = 0;
        	c = a + b;
        	printf("%d %d", a + b, c);
        	return 0;
        }
        

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kvVFWR2y-1644641270219)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644641241885.png)]


​ 经历了这死亡八道题,你的表情是如何呢?是 ฅ՞•ﻌ•՞ฅ?是 (-̩̩̩-̩̩̩-̩̩̩-̩̩̩-̩̩̩___-̩̩̩-̩̩̩-̩̩̩-̩̩̩-̩̩̩)?是 Σ(-`Д´-ノ;)ノ?还是 ∑(O_O;)呢?选择你的答案吧。


浮点型在内存中的存储

常见的浮点数:

  1. 字面型浮点数:3.14159
  2. 1E10->1.0*10^10
  3. 浮点数家族包括: float、double、long double 类型。
  4. 浮点数表示的范围:float.h中定义

在VS2019中输入#include<float.h>,然后右键->转到文档

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P2TreYbN-1644641270220)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644626163041.png)]

从第85行开始就有关于float类型的具体内容了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RYqAU144-1644641270222)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644626229517.png)]

  1. 一个浮点数存储的例子

    #include<stdio.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;
    }
    

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-egfR8wtN-1644641270223)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644626368582.png)]

    震惊!第一个打印的*pFloat怎么不是9.000000?第二个人打印的n怎么不是9.0?

    那么其实整数与浮点数的存储方法不同

  2. 浮点数的存储规则

    浮点数无原码 反码 补码

    1. 根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:

      (-1)^S * M * 2^E
      (-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
      M表示有效数字,大于等于1,小于2。
      2^E表示指数位。

       举个例子:5.5写成IEEE754形式
      

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C0aI3544-1644641270224)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644626835737.png)]

    1. IEEE 754规定:

      1. 对于32位(float)的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MiwTY55y-1644641270226)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644627655903.png)]

      2. 对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i0ZQYc7p-1644641270227)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644627891505.png)]

      3. IEEE 754对有效数字M和指数E,还有一些特别规定。

        1. 存进去:
          1. 有效数字M:前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
            IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分
          2. 指数E:IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023
        2. 拿出来:
          1. E不全为0或不全为1:指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1
          2. E全为0:浮点数的指数E等于==1-127(或者1-1023)==即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数
          3. E全为1:如果有效数字M全为0,表示±无穷大(正负取决于符号位S)(不做深入研究)
  3. 刚开始的例子讲解:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m5eqjDD0-1644641270229)(E:\博客\C语言专区\C语言进阶版本\精准分析各种数据在内存中的存储.assets\1644628439468.png)]



通过这一篇文章,相信你已经对数据在内存中的存储已经得心应手了,下一篇文章,我们会进行高难度指针的探索,希望你不要害怕做好准备!加油 !


喜欢这篇文章的话,请一件三连!感谢!!!

  • 35
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 28
    评论
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加勒比海涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值