• 【C语言】整形数据的存储


    一、整形计算机表示及内存中的存储

    1.整形计算机表示

    数值有不同的表示形式——2进制【0b开头】、8进制【0开头】、10进制【没有前缀】、16进制【0x开头】等。

    2进制序列写成16进制序列时,4个比特位和为一个【分别对应2的0、1、2、3次方】,每两个放到一块,前边再加上0x

    内存中本质还是2,但是为了我们分析/编译器显示方便,一般会表示16进制。

    整数的二进制的三种表示形式

    原码:直接通过正负的形式写出的二进制序列就是原码

    反:原码符号位不变,其他位按位取反得到的就是反码

    补:反码+1

    另外:原码除了可以通过补码产生的逆运算得到,也可以由补码+1,在按位取反(符号位除外)得到。

    三种表示方法均有符号位数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位表示各不相同。

    正整数

    正整数原反补相同

    负整数

    写出原码,根据计算规则算出反码补码。

    2. 整形内存表示——补码

    对于整形,计算机存放的其实是补码的二进制序列。

    原因

    在计算机系统中,数值一律用补码来表示和存储。

    原因

    使用补码,可以将符号位和数值域统一处理;-----1

    同时,加法和减法也可以统一处理(CPU****只有加法器)-----2

    此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。-----3

    二、大小端字节序详解

    我们已经知道整数在计算机内部统统存的都是补码,但是我们可以看到他们显示的顺序好像跟我们以为的补码不太一样,这里就涉及到了大小端字节序的问题。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zPByoo4F-1657982303258)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715142543310.png)]

    1. 什么是大小端字节序

    大端(存储):数据低位存储在内存的高地址、数据高位存储在内存的低地址。

    小端(存储):数据高位存储在内存的高地址、数据低位存储在内存的低地址。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-npuTNjzc-1657982340352)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715142900324.png)]

    2.为什么会有大小端字节序之分

    在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8 bit。

    但是在C语言中除了8 bit的char之外,还有16 bit的short型,32 bit的long型(要看具体的编译器)

    另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。

    简言之,只要超过两个字节以上就有顺序问题,char、double等都有——内存存储问题。

    但是存储顺序——五花八门,其他的太麻烦,正放反放两种比较方便。

    【画图时无特殊要求时,低地址到高地址是根据自己习惯决定的】

    补充

    大端存储和小端存储都取决于硬件,市面上大部分都是小端存储,这些跟编译器没有什么关系

    例如,x86结构就是小端模式

    3.一道真题

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kDMOzDEv-1657982303261)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715143941474.png)]

    所以我们只要拿到它的第一个字节存储的值看是0还是1,就可以判断。——这里体现了指针类型的意义。

    所以,答案可以为

    #include 
    int check_sys()
    {
    	int a = 1;
    	return *(char*)&a;
    }
    int main()
    {
    	int ret = check_sys();
    	if (ret == 1)
    		printf("小端\n");
    	else
    		printf("大端\n");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    补充:【&a,是地址编号,本质上是一个整形】——所以打印的时候可以以%d形式打印。

    4.练习题

    1)该段程序输出什么?

    #include 
    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; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Som7O7eL-1657982303262)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716192549764.png)]

    在这里插入图片描述

    2)下面程序输出什么?

    #include 
    int main()
    {
        char a = -128;
        printf("%u\n",a);
        return 0; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hq9MZyk7-1657982303263)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716192409545.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VKwAFEyj-1657982303265)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716190524817.png)]

    3)下面程序输出什么?

    #include 
    int main()
    {
        char a = 128;
        printf("%u\n",a);
        return 0; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    在这里插入图片描述

    4)

    int i= -20;
    unsigned  int  j = 10;
    printf("%d\n", i+j); 
    
    //按照补码的形式进行运算,最后格式化成为有符号整数
    
    • 1
    • 2
    • 3
    • 4
    • 5

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f2PJIman-1657982303267)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716202416312.png)]

    在这里插入图片描述

    5)

    unsigned int i;
    for(i = 9; i >= 0; i--)
    {
        printf("%u\n",i);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xL2D5AuS-1657982303268)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716203536552.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BgHdou9c-1657982303269)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716202652015.png)]

    6)

    int main()
    {
       char a[1000];
       int i;
       for(i=0; i<1000; i++)
       {
           a[i] = -1-i;
       }
        printf("%d",strlen(a));
        return 0; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cEzoKWoL-1657982303270)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716205114003.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0sxKdUCy-1657982303271)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716205130467.png)]

    7)

    #include 
    unsigned char i = 0;
    int main()
    {
       for(i = 0;i<=255;i++)
       {
           printf("hello world\n");
       }
       return 0; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lgrgJWbl-1657982303272)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716211221910.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EiscByoU-1657982303273)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220716211201446.png)]

    三、重点强调

    1.整数内存存储形式——补码

    2.整数运算——补码,原码/其他形式打印

    3.特别小心无符号数,同时小心strlen的返回值。

    4.截断的方法——从补码的低位开始,整型提升方法——复习操作符之整形提升算数转换那块。

    5.大小端字节序存储这块知识多与指针练习题紧密结合,特别小心。

  • 相关阅读:
    驱动——platform驱动总线三种匹配方式
    PostgreSQL基于Citus实现的分布式集群
    QAD1 持续交付 Continuous Delivery
    【VLN学习内容LIST】
    机器学习——boosting之XGBoost(未完)
    如何判断对象是否该被回收(引用计数法、可达性分析算法)
    android 车载widget小部件部分详细源码实战开发-千里马车载车机framework开发实战课程
    You may use special comments to disable some warnings
    python(进阶篇)——selenium自动化操作浏览器
    基于Hardhat编写合约测试用例
  • 原文地址:https://blog.csdn.net/moteandsunlight/article/details/125826210