当前位置: 首页 > article >正文

是否还在疑惑数据存储的大小端和所谓的整形提升呢,那就来看看吧

何为大小端字节序,何为整形提升,今天诸君便可一睹芳容。

再C语言知识的海洋中尽情遨游吧,未来的那位顶端程序员。


目录

 整数在计算机内存中的储存

大小端字节序判断

 整形提升


 整数在计算机内存中的储存

这里就简单讲一下这个整形在内存的储存吧,等下我们也是要这个知识点来讲解整形提升。

首先我们就来了解一下计算机中的整数二进制表达方法,其中有原码,反码,补码。

负数的原码补码反码

原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。

反码:原码的二进制中,符号位不变,其它位取反,即可得到反码。

补码:反码+1。即可得到补码。

注:正数的原码补码反码全都相同


 而整数在计算机内存中是以补码的形式来存储的,这是为什么呢?

这是因为用补码,可以将符号位和数值域统⼀处理; 同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

运算过程相同是:原码可以符号位不变,其它位取反,再+1得到补码,而补码一样可以取反再+1得到原码。


大小端字节序判断

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

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

大小端字节序的判断也比较简单,而这两种的不同,是大端还是小端储存在C语言中取决于编译器。那下面我们先看一段代码。

#include <stdio.h>
int main()
{
	int a = 0x11223344;

	return 0;
}

一段很简单的代码,0x11223344,为十六进制数11223444,在存储刚好两位数就是一个字节,在这个十六进制数中跟我们平常的个位,十位,百位一样靠右的为低位即44为低位

这里我们可以通过查看编译器内存的存储方式来判断编译器的存储方式是大端储存还是小端存储。

从上图左边为低地址,往右地址变高,然后我们发现44在低地址处,那么我们就可以判断出在VS中的存储模式为小端模式 。

 那么为什么会有大小端之分:

这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着⼀个字节,⼀个字节为8 bit 位,但是在C语言中除了8 bit 的 char 之外,还有16 bit 的 short 型,32 bit 的 long 型(要看 具体的编译器),另外,对于位数⼤于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。因此就导致了⼤端存储模式和小端存 储模式。

简单来说就是:存储方式的排列方式是区分的,有的机器就是大端,有的就是小端,如人的习惯一样。有人喜欢吃东西加香菜有人不喜欢。


 整形提升

这个知识我就用一些代码来边看边了解。我们可以更好了解整形提升。下面是一段代码,认真思考一下哟。

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

	return 0;


}

这里signed char为有符号的char数据,unsiged char为无符号的char数据,那么单单一个char为有符号还是无符号呢,这时还是看我们的编译器的默认情况了,在VS中默认单个char,int等类型数据为有符号的。

回到上面的代码中也就是a和b其实都是一样的数据,且赋值都为-1,那么他们的打印结果也是一样的了。那么他们的打印结果是什么呢,下面我们分析一下

上面列出一步一步的操作:

第一步:列出赋值整数的补码。

第二步:因为char只有1个字节的空间也就是8个bit,所以我们截取低位(靠右边的位置)8个数。

第三步:如果变量要打印出来则先进行整形提升,根据变量类型有无符号提升,有符号则按符号位的数字补全其他高位,无符号类型则高位补0.

第四步:根据printf的占位符打印,%d是以有符号的10进制打印出数据,如果%u则表示以无符号的10进制打印出来。注:打印的就是整形提升得到的数

 然后根据上方步骤我们在看看最后一个打印结果的解析:

unsigned char c = -1;

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

这里先是按照第一第二步列出数据补码,截取得到:11111111  ,然后整形提升,这里数据类型为unsigned char;那我们高位补0.得到00000000000000000000000011111111。最后一步以%d打印出结果以有符号的形式打印10进制,这里00000000000000000000000011111111,为正数,补码等于原码打印出来就是255了。我们看一下打印结果。


最后我们再看一段代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
	char a = -128;

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

	



	return 0;
}

这里也是为了巩固知识,我们还是来按照上面的四步,一步一步来。

第一步:列出整数的补码得到11111111111111111111111110000000。

第二步:然后还是char类型,截取低8位,得到10000000。

第三步:整形提升,符号类型为char,VS默认为有符号,则补高位按符号位1补,得到11111111111111111111111110000000。

第四步:这里有两个打印方式一个是%d,一个是%u,%d为有符号的打印则这里为负数需先把11111111111111111111111110000000变为原码,得到10000000000000000000000010000000然后打印出来为-128.

%u为无符号的打印则这里就会将11111111111111111111111110000000作为原码(正数的原,反,补码相同)打印出来就得到一个很大的数4294967168。

那我们来看一下结果:

 


这篇文章结束了哟,诸君懂否。


http://www.kler.cn/a/272723.html

相关文章:

  • 2025.1.15——四、布尔注入
  • 【2024年华为OD机试】 (C卷,100分)- 小明找位置(Java JS PythonC/C++)
  • MySQL程序之:使用类似URI的字符串或键值对连接到服务器
  • 数据仓库复用性:业务需求复用性设计
  • 意图颠覆电影行业的视频生成模型:Runway的Gen系列
  • LabVIEW 程序中的 R6025 错误
  • 【JVM】(内存区域划分 为什么要划分 具体如何分 类加载机制 类加载基本流程 双亲委派模型 类加载器 垃圾回收机制(GC))
  • vue xlsx读取文件时,日期转换为了天数
  • 【QT入门】VS2019和QT Creator如何添加第三方模块
  • C#,数值计算,矩阵相乘的斯特拉森(Strassen’s Matrix Multiplication)分治算法与源代码
  • Vue2 父子组件某一属性的双向绑定
  • 【软件测试知识】什么是持续集成?
  • 鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:RichText)
  • 社区居民医疗健康系统 微信小程序
  • LabVIEW提升舱救援通讯监测系统
  • 香农公式的理解
  • 【Nuxt3】plugins目录介绍和nuxt3插件的用法
  • HackTheBox WifineticTwo
  • 速盾cdn:cdn节点缓存内容不一致怎么办?
  • leetcode 3080
  • 奇数乘积(C语言)
  • Python数据分析-Matplotlib1
  • IOS面试题object-c 131-135
  • TSINGSEE青犀AI烟火识别等算法打造电瓶车消防安全解决方案
  • Docker进阶:离线安装docker社区版(docker-18.06.3-ce)
  • vite+vue3项目中svg图标组件封装