首页 > 其他分享 >C语言---数据存储

C语言---数据存储

时间:2023-09-10 15:00:45浏览次数:34  
标签:char 存储 int 补码 C语言 --- 整型 类型 原码


我们知道一个变量在内存中存储是要开辟一块内存空间来存储的,那么该为这个变量开辟多大的内存空间呢?这个要依据变量的类型,我们知道int类型的变量大小是4个字节,char类型的变量大小是1个字节,创建一个变量时,根据其类型来为变量申请对应大小的空间。


问题:那么不同类型的数据在内存中到底是如何存储的呢?

int a=10;//创建一个int类型的变量a,初始化为10,将其存储于内存中。

我们知道存储变量a到内存中会申请4个字节的空间。那么申请到空间以后又是如何存储的呢?

计算机底层处理时只能识别01代码,所以存入内存的数据在进行处理时也是以二进制形式来处理的,(讲解时以有符号数为例)只不过其存在不同的形式,即原码,反码,补码。

概念引入:

计算机中的有符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值三种表示方法各不相同。

原码、反码、补码

原码:

将数值按照正负数形式表示为二进制形式即可

反码:

正数的反码与原码相同,负数在原码的基础上,符号位不变,其余位按位取反得到反码

补码:

正数的补码与原码、反码相同,负数在补码的基础上最低位加一得到补码


对于整型数据来说,在内存中存储的其实是以补码形式存储的。

我们来看一张图片:

定义了一个有符号整型变量a=-10;

C语言---数据存储_整型

内存监视窗口:

C语言---数据存储_原码_02

通过对内存的监视(以十六进制展示,4位二进制代表一位16进制 ),我们可以看到,a的补码的16进制为0xff ff ff f6,该整形数值在内存中确实存入了其补码(存入的是0x f6 ff ff ff,这个与大小端有关,在此不展开讲解)。

为什么是以补码形式存在内存中呢?在此简单补充一下


在计算机系统中,整型数值一律用补码来表示、存储、运算。是因为用补码可以将符号位和数值位统一处理。并且,补码与原码的相互转换的运算过程相同,无需额外的硬件电路。


整型数据包括int(signed int、unsigned int)、short(signed short、unsigned short)、long int(signed long int、unsigned long int)、long long(signed long long、unsigned long long)、char(signed char、unsigned char)


  • signed 表示有符号类型
  • unsigned 表示无符号类型

所以以上整型数据在内存中的存储和运算均是以二进制补码形式完成的。



PS:其中为什么字符类型也属于整型数据呢?是因为每一个字符存储都对应着一个ascii码值,ascii码值是整数类型,所以字符的存储可以理解为整数的存储,所以把char类型也归结为整型数据。


那我们再以整型数据中有符号char类型变量存储为例:

先看一张图片:

C语言---数据存储_原码_03

按照我们前面所讲,char类型也属于整形数据,所以在内存中存储时应该存入补码形式,但是通过对内存的监视,可以看到只有低位的8个bit位被存入内存,这是为什么呢?


这是因为-3是一个signed int类型的数据,大小为4byte,我们要把其存入到大小为1byte的char类型变量中,有一部分存不下,所以发生了截断,只保留低位。


那么如果要进行算数运算计算机是如何处理的呢?

来看一段代码

#include <stdio.h>
int main()
{
	char a = -3;
	      //原 10000000 00000000 00000000 00000011
	      //反 11111111 11111111 11111111 11111100
	      //补 11111111 11111111 11111111 11111101
          //补码16进制 0xff ff ff fd
	char b = 1;
	      //原/反/补 00000000 00000000 00000000 00000001
         //补码16进制 0x 00 00 00 01
	char c = a + b;
	printf("%d %d", c, a + b);
	return 0;
}

通过前面的分析我们可以得出把int类型的数据存入char类型变量,会发生截断,存储低8位bit位到char变量中,那么在发生整型算数运算时,计算机又是如何处理的呢?

此处我们引入整型提升的概念。


C的整型算术运算总是至少以缺省整型类型的精度来进行的。

        为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升


通俗来讲,就是整型中的char、short类型在进行算数运算前,会被转为普通整型再进行算数运算。

整型提升规则:

  • 首先提升时参照的是数据原来的类型,如果被提升的变量是无符号字符型/无符号短整型,那么在进行整型提升时,在其补码高位补0到共32个bit位。
  • 如果被提升的变量是有符号短整型/有符号字符型,则根据其符号补足补码高位,再进行运算。

那么前面对char类型变量a+b的运算通过分析可得到:

C语言---数据存储_补码_04

计算完成后,我们以不同的形式对a+b的形式进行打印(打印时打印的是原码形式对应的值,对于负数要把其变回原码形式)

printf("%d\n", a + b);
	printf("%d\n", c);
	printf("%u\n", c);

代码运行结果如下图示:

C语言---数据存储_整型_05


为什么相同的计算过程但是打印出的值却不同呢?

打印其实实质上是反映计算机对某个数值的看待方式,同一个数看待方式不同自然打印出的结果就不同了。

让我们来逐个分析:

1)

printf("%d\n", a + b);

C语言---数据存储_数据_06

此种情况下,a和b整型提升后,以补码形式运算,得到计算结果,以有符号int类型打印,打印时打印数据对应的原码的值,a+b运算结果<0,将其变为原码形式打印,为-2。

2)

printf("%d\n", c);

C语言---数据存储_原码_07

此种情况下,a和b整型提升后,以补码形式运算,得到计算结果,将计算结果存在char类型变量c中,发生截断,以有符号int类型打印,再发生整型提升,c<0,将其变为原码形式打印,为-2。

3)

printf("%u\n", c);

C语言---数据存储_整型_08

此种情况下,a和b整型提升后,以补码形式运算,得到计算结果,将计算结果存在char类型变量c中,发生截断,以无符号int类型打印,前面提到,打印是计算机以不同角度看待数据的结果,以无符号整数类型打印,那么计算机处理整型提升后c的补码时,就会认为c是一个无符号类型整型变量,那么对于无符号类型变量,可以将其理解为恒正值,所以其补码就是原码,所以会打印一个很大的数,即

C语言---数据存储_补码_09


总结:

以不同类型打印同一数值,是计算机以不同角度看待数据的结果。

对于浮点型数据在内存中的存储,与整型相比又有很大不同,我后续会继续和大家分享,如果本片文章有什么错误之处,欢迎在评论区指出或者私信我^-^,如果觉得本篇文章不错,希望您给个一键三连,我们下期再见!

C语言---数据存储_原码_10

C语言---数据存储_整型_11

标签:char,存储,int,补码,C语言,---,整型,类型,原码
From: https://blog.51cto.com/u_16191221/7425709

相关文章

  • The adjoint technique - 2019
    SIGGRAPH2019:DeepLearningforContentCreationandReal-TimeRendering-Theadjointtechnique-Video作者:JosStam,NVIDIASIGGRAPH 2019InthistalkIwillpresenttheadjointmethod–-ageneraltechniqueofcomputinggradientsofafunctionorasim......
  • MinIO对象存储
    MinIO简介MinIO基于ApacheLicensev2.0开源协议的对象存储服务,可以做为云存储的解决方案用来保存海量的图片,视频,文档。由于采用Golang实现,服务端可以工作在Windows,Linux,OSX和FreeBSD上。配置简单,基本是复制可执行程序,单行命令可以运行起来。MinIO兼容亚马逊S3云存储服务接......
  • 设计模式-中介者模式
    中介者模式定义+用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显示地互相引用,从而使耦合松散,并且可以独立地改变他们的交互。UML类图使用场景+一般用于一组对象以定义良好但复杂的方式进行通信的场景,比如窗体的Form或者web页面asp+想定制一个分......
  • C#开发的基础工具类集合 - 开源研究系列文章
          今天发布一个基础工具类代码集合。      以前有发布过一个类似的类库(见博文:Magical平台类库代码分享),不过那个版本有点久了,也没有这次这个全面,这次发布的是一个很多地方用到的基础类库代码。1、项目目录;项目底下就是DLL类库的代码: 2......
  • P8029 [COCI2021-2022#3] Akcija 题解
    注:这篇题解中涉及到的所有概念均会在其第一次出现时用斜体标出,有些概念给出了定义,而有些概念的含义请自行意会。定义状态为选了的物品数\(a\)与相应总价格\(b\)的二元组\((a,b)\)。相应地定义状态之间的大小关系、最优状态与状态和状态的加法运算\((a_1,b_1)+(a_2,b......
  • 无涯教程-JavaScript - COUPPCD函数
    描述COUPPCD函数返回一个数字,该数字表示结算日期之前的上一个息票日期。语法COUPPCD(settlement,maturity,frequency,[basis])争论Argument描述Required/OptionalSettlement证券的结算日期。证券结算日期是指在发行日期之后将证券交易给买方的日期。Required......
  • Spring Boot 中使用 Poi-tl 渲染数据并生成 Word 文档
    本文Demo已收录到demo-for-all-in-java项目中,欢迎大家star支持!后续将持续更新!前言产品经理急冲冲地走了过来。「现在需要将按这些数据生成一个Word报告文档,你来安排下」项目中有这么一个需求,需要将用户填写的数据填充到一个Word文档中,而这个Word文档是人家给定......
  • 基于微信小程序的助农电商系统设计与实现-计算机毕业设计源码+LW文档
    摘 要随着互联网技术的发展,传统的农产品销售迎来了机遇,我国是个农业大国,如何推广农产品的销售是农产品企业非常关注的事情。随着电子商务多元化的发展,各地方特产、农产品逐渐转移到线上销售。在互联网的帮助下,带动农产品企业打开销路,促进农产品可持续发展。同时,通过基于微信小......
  • 代码随想录算法训练营-回溯算法|491.递增子序列
    491. 递增子序列 不对原数组进行排序,利用set对同层的子集进行去重。1classSolution:2deffindSubsequences(self,nums):3result=[]4path=[]5self.backtracking(nums,0,path,result)6returnresult78......
  • 无涯教程-JavaScript - COUPNCD函数
    描述COUPNCD函数返回一个数字,该数字表示结算日期之后的下一个息票日期。语法COUPNCD(settlement,maturity,frequency,[basis])争论Argument描述Required/OptionalSettlement证券的结算日期。证券结算日期是指在发行日期之后将证券交易给买方的日期。Required......