【C语言】整型提升与char取值范围

整型提升介绍

C语言中整型算术运算总是至少以缺省(默认)整型类型的精度来进行的。为了获得这个精度,表达式中字符、短整型操作数在使用前被转换为普通整型。而这个过程是悄悄发生的。

整型提升的意义:

表达式的整型运算要在CPU的相应运算器件内执行,CPU整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。

因此,即使是进行两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。

通用CPU难以直接实现两个8bit字节的直接加法运算。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行。

举个例子:

char a = 20;
char b = 130;
char c = a + b;
printf("%d\n", c);

根据我们上面说的,在这段代码中,其实会先把a、b提升为整型类型才计算。

怎么整型提升

有符号整数的整型提升是按照变量的数据类型的符号位来提升的;

无符号整数提升,高位就补0。

回到我们刚才的例子:

char a = 20;

20本身是个整数,整数存到整型中应该有32个比特位(bit),因为是个正整数,它的原码、反码、补码相同:

00000000000000000000000000010100

但是我们现在要将它存放到char类型(只有1个字节,也就是8bit)中去,会发生截断。

我们只能存下这个:

00010100

 同样的道理,b里面我们只能存的是:

10000010

那么现在,c里面放的是什么?

因为我们已经知道,a+b在具体计算前会先发生整型提升,我们也知道整型提升的规则是:有符号整数的整型提升是按照变量的数据类型的符号位来提升的;无符号整数提升,高位就补0。因为是a、b是有符号整型,所以按照符号位来提升:

00010100 ---> 00000000000000000000000000010100 //因为符号位为0
10000010 ---> 11111111111111111111111110000010 //因为在提升时认为符号位是1a + b:      11111111111111111111111110010110
11111111111111111111111110010110 ---> 10010110 //因为c只能存8位,又截断

所以c里面存的是10010110,但是这还没有结束,最后我们要打印的时候用的是%d,这是打印一个有符号的整型,我们此时又要进行提升

10010110 ---> 11111111111111111111111110010110 
//因为%d是有符号整型,提升时按符号位提升,而1被视作符号位

而此时%d打印出来的结果并不是这个二进制序列直接翻译成十进制的结果,因为内存中存储的是补码,而我们要找出它的原码直接翻译的结果才是我们会打印出来的值:

因为现在的符号位上还是1,被当做负整数,所以原码、反码、补码并不相同,我们可以通过将补码取反+1的方法得到原码:

11111111111111111111111110010110 ---> 10000000000000000000000001101001
//取反的规则是符号位不变,其它位取反
10000000000000000000000001101001 ---> 10000000000000000000000001101010
//将取反的结果再加1

最后这个原码直接翻译:因为%d是有符号整数,符号位为1所以是负数,1101010转换为10进制是106,所以最后打印的结果就是-106。

另一种视角(char取值范围)

char a = 20;
char b = 130;
char c = a + b;
printf("%d\n", c);

关于这段代码,通过上面的讲解我们多次感受到了整型提升, 这是我们从内存中存储了什么的角度一步步去看为什么结果是-106的,其实还有另一个角度可以解释结果为什么结果为-106:

我们不要忘记char类型的取值范围,一般情况下char就是指的有符号的char,取值范围是-128~127(而unsigned char范围是0~255,都是256个不同数值)。

(本文不解释为什么是这样)这是我们char能存储的值的示意图,就像一个轮回:

所以其实130大于char的取值,我们无法将其存进b里。

我们可以通过监视看看b存的是什么:

可以看到我们存的值就是-126,那么a+b就变成了-106。

 那么为什么b里面会存为-126呢?在上面我们已经得到了a+b的二进制序列被截断为8bit,也就是c里实际存的二进制序列是:

10010110

在计算器中我们可以观察到这个二进制序列直接翻译为10进制的值是150。

但是对于char而言,这个二进制序列可不是代表150。 为什么?

因为char只能存8bit,且为有符号类型,所以最高位是符号位,1说明是负整数,那么说明存的是补码,原码需要计算,根据取反(符号位不变,其他位按位取反)再+1,我们得到原码是:

10010110 ---> 11101001 ---> 11101010取反          加1

最高位是符号位,代表是负数,而剩下的有效位转化为十进制是106。所以原码就是106,

补充:char能存储的补码

我们知道char有8位,而每一位非0即1,所以我们能存的补码就是00000000~11111111,又因为char是有符号的char,所以当最高位变为1的时候我们会将其作为符号位而非有效位,而存的又是补码,在翻译为10进制数的时候要先取反加1得到原码,直接翻译才是其对应的10进制数。

其中10000000的求原码比较特殊,取反加1后我们得到100000000是9位的,而char只能存8位,所以会变为00000000,但是我们却不将其翻译为10进制的0而是-128。除了这个特殊情况外,其它情况都可以正常方式得到原码:

通过这张图,你应该就理解了上面那个“轮回”的图为什么是那样的了。

我们还可以发现,除了127加1得到的是-128的特殊情况,其他时候补码加1就是10进制加1的效果。 

到此,整型提升和char取值范围的讲解就结束了,祝阅读愉快^-^ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/15397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ wasm 使用教程

环境搭建 git clone https://github.com/emscripten-core/emsdk.gitgit pull./emsdk install latest./emsdk activate latestsource ./emsdk_env.sh./emcc -v && ./emcc c11__Thread_local.c -s WASM_WORKERS --threadprofiler --memoryprofiler -v -o test.html &…

Sentinel的授权规则详解

文章目录 1、授权规则1.1、基本规则1.2、如何获取origin1.3、给网关添加请求头1.4、配置授权规则 2、自定义异常结果2.1、异常类型2.2、自定义异常处理 🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学…

深度学习中的优化算法一(Pytorch 18)

一 优化和深度学习 优化算法 使我们能够 继续更新模型参数, 并使损失函数的值最小化。这就像在训练集上评估一样。事实上,任何满足于将优化视为黑盒装置,以在简 单的设置中最小化目标函数的人,都可能会知道存在着一系列此类“咒…

STM32 学习——2. PWM

这个项目将会不断改变pwm占空比,使用proteus示波器进行观察。 1. proteus8.15 原理图 2. cubemx 上图是配置外部晶振 上图配置在proteus中没啥作用,注意: 在实际开发板中,一定要配置它,不然下一次你写不进代码。 上图配…

番外篇 | YOLOv5-SPD:用最简单的方式完成低分辨率图像和小目标检测升级

前言:Hello大家好,我是小哥谈。论文提出了一个新的CNN构建模块称为SPD-Conv,用来替换每个步长卷转层和每个池化层(从而完全消除它们)。SPD-Conv由一个空间到深度(SPD)层和一个非步长卷积(Conv)层组成。本文详细介绍了如何在YOLOv5中引入SPD-Conv,助力助力低分辨率与小…

自用网站合集

总览 线上工具-图片压缩 TinyPNG线上工具-url参数解析 线上工具-MOV转GIF UI-Vant微信小程序版本其他-敏捷开发工具 Leangoo领歌 工具 线上工具-图片压缩 TinyPNG 不能超过5m,别的没啥缺点 线上工具-url参数解析 我基本上只用url参数解析一些常用的操作在线…

“等保测评与安全运维的协同:保障企业网络安宁

"等保测评与安全运维的协同:保障企业网络安宁"是一个涉及信息安全领域的重要话题。这里,我们可以从几个方面来探讨这个主题。 1. 等保测评(等级保护测评) 等保测评,即信息安全等级保护测评,是依…

[DDR5 Jedec 3]DDR5 SDRAM 状态图 和 基本功能

3000字, 依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解DDR》 3.1 简化状态图 来源: Jedec Proposed DDR5 Full spec 缩写功能ACT激活PRE预充电PRE_A全部预充电MRS寄存器集模式REF刷新TEN边界扫描模式ReadRD, RDS4, RDS8Read ARDA, RDS4A, RDS8AwriteWR, WRS4…

Ollama:一个在本地部署、运行大型语言模型的工具

Ollama:一个在本地部署、运行大型语言模型的工具 Ollama部署、运行大型语言模型概述安装配置Ollama命令模型库使用示例自定义模型从GGUF导入自定义提示从PyTorch或Safetensors导入 开启服务REST API卸载Ollama One-API概述One-API管理本地模型 Open WebUI概述Docker…

【Linux学习】深入了解Linux中进程状态及其转换

文章目录 进程状态进程排队进程的状态(运行,阻塞,挂起)进程的七个状态 孤儿进程 进程状态 进程 task_struct 可执行程序 进程不是一 直在运行的,可能在等待软硬件资源,比如scanf后,程序停止运…

邮件系统数据面临的安全问题及解决方法

随着电子邮件的普及,邮件系统已成为企业、学校、个人等用户之间进行信息交流的重要工具。然而,随着数据量的增加和用户对邮件系统的依赖,邮件系统数据安全问题也逐渐凸显。下面U-Mail技术张工就给大家讲解一下邮件系统数据面临的主要安全问题…

Ardupilot开源代码之Rover上路 - 后续3

Ardupilot开源代码之Rover上路 - 后续3 1. 源由2. 深度配置2.1 编码器2.2 WS2812B LED灯带2.3 4GLTE超视距2.3.1 摄像头2.3.2 QGC OSD虚拟遥控2.3.3 QGC外接JoyStick遥控 2.4 伴机电脑供电 3. 实测效果4. 遗留&后续4.1 设置倒车按钮4.2 MP无法连接ESP82664.3 高精度编码器问…

【知识拓展】ngrok-高性价比的内网穿透工具

前言 使用google colab运行的web应用无法打开进行测试。 第一时间想到是否有相关工具能将内网映射到外网供访问。于是找到了ngrok。 ngrok 是什么,我们为什么要使用它? ngrok官网是一个全球分布的反向代理,无论您在哪里运行,它…

【车载开发系列】Autosar中的VFB

【车载开发系列】Autosar中的VFB # 【车载开发系列】Autosar中的VFB 【车载开发系列】Autosar中的VFB一. 什么是VFB二. VFB的优点与缺点1)VFB的缺点2)VFB的好处 三. RTE与VFB之间关系四. 总线架构模式 一. 什么是VFB Virtual Functional Bus。它就是虚拟…

解决Vue项目部署到服务器之后前端向后端发送请求报错404的问题(centos使用docker实现nginx的反向代理)

场景重现: 由于现在流行前后端分离的部署方式,但是按照正确方法部署(如何部署可参考:)之后,发现明明前后端都部署好了并且运行成功,但是前端发送的请求都是404。明明在vue项目中配置了跨域的相…

【Spring Boot】深度复盘在开发搜索引擎项目中重难点的整理,以及遇到的困难和总结

💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录文章:【Spring Boot】深度复盘在开发搜索引擎项目中重难点的整理,以及遇到的困难和总结 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 什么是搜索引…

AJAX初级

AJAX的概念: 使用浏览器的 XMLHttpRequest 对象 与服务器通信 浏览器网页中,使用 AJAX技术(XHR对象)发起获取省份列表数据的请求,服务器代码响应准备好的省份列表数据给前端,前端拿到数据数组以后&#xf…

TENT: FULLY TEST-TIME ADAPTATION BY ENTROPY MINIMIZATION--论文笔记

论文笔记 资料 1.代码地址 https://github.com/DequanWang/tent 2.论文地址 https://arxiv.org/abs/2006.10726 1论文摘要的翻译 在这种完全测试时适应的情况下,模型只有测试数据和自身参数。我们建议通过测试熵最小化(tent)进行适应&…

虚拟化技术[2]之存储虚拟化

存储虚拟化 存储虚拟化简介存储虚拟化一般模型存储虚拟化实现方式基于主机存储虚拟化基于存储设备存储虚拟化基于网络存储虚拟化 案例分析:VMFSVMFS功能 存储虚拟化简介 存储虚拟化:将存储网络中的各个分散且异构的存储设备按照一定的策略映射成一个统一…

C++学习笔记(19)——模板

目录 模板参数与非类型模板参数 模板参数 类型模板参数——传递类型 非类型模板参数——传递数量 C11希望array替代静态数组,但实际上vector包揽了一切 模板总结 优点: 缺点: 模板特化:针对某些类型进行特殊化处理 特化…