C++ 学习 关于无符号数的计算

C++ 学习 关于含无符号数表达式的计算

🌈 哈喽,失踪人口回归

这篇blog 来源于C++ 的学习 当然C语言同样适用

C++ Primer 的笔记

🌿让我们从一个问题开始 如果你回答对了 那么就可以跳过了~

对于下面的问题

//读程序写结果。
unsigned u = 10,u2= 42;
std:: cout << u2 - u<< std::endl;
std::cout <u - u2 << std:: endl;int i = 10,i2 =42;std::cout<< i2 -i<< std::endl;  
std::cout << i - i2<< std::endl; 
std::cout << i - u<< std::endl; 
std::cout << u- i<< std::endl;unsigned k1 = 42,k2 = 10;
std::cout<<k2-k1<<std::endl;
std::cout<<k1-k2<<std::endl;

🤔尝试一下最终输出什么结果


揭晓答案!

32
4294967264
32
-32
0
0
4294967264
32

🤭 你答对了嘛 没有的话 可以接下去看(我刚开始也是懵的其实~)

🌺 首先明确一下,不管是C还是C++ 类型都是很重要的! 所以先看看类型转换相关的内容,然后再来讨论上面无符号表达式转换的内容~

关于类型转化

⭐️C/C++里面类型是很重要的!你能判断出下面每执行一行后,相应变量的值不?(嘻嘻 梅开二度~)

bool b=32;
int i=b;
i=3.14;
double pi=i;
unsigned char c= -1;
signed char c2=256;

答案揭晓!

bool b=32;//b为真
int i=b;//i=1
i=3.14;//i=3
double pi=i;//pi=3.0
unsigned char c= -1;//若char 为8bit c为255
signed char c2=256; //若char 为8bit 那么c2是未定义的 溢出啦

当我们把一个非布尔类型的算术值赋给布尔类型时,初始值为0则结果为false,否则结果为true。

当我们把一个布尔值赋给非布尔类型时,初始值为false 则结果为0,初始值为true 则结果为1。

当我们把一个浮点数赋给整数类型时,进行了近似处理。结果值将仅保留浮点数中小数点之前的部分。

当我们把一个整数值赋给浮点类型时,小数部分记为0。如果该整数所占的空间超过了浮点类型的容量,精度可能有损失。

当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。例如,8比特大小的unsigned char可以表示0至255区间内的值,如果我们赋了一个区间以外的值,则实际的结果是该值对 256取模后所得的余数。因此,把-1赋给8比特大小的unsigned char所得的结果是255。

当我们赋给带符号类型一个超出它表示范围的值时,结果是未定义的(undefined)。此时,程序可能继续工作、可能崩溃,也可能生成垃圾数据。

含有无符号类型的表达式

尽管我们不会故意给无符号对象赋一个负值,却可能(特别容易)写出这么做的代码。例如,当一个算术表达式中既有无符号数又有int值时,
那个int值就会转换成无符号数。把int转换成无符号数的过程和把int直接赋给无符号变量一样:

unsigned u= 10;
int i =-42;
std::cout << i+i<< std::endl; //输出-84
std::cout<< u +i << std::endl;//如果int占32位,输出4294967264
//理由是 int 是8个字节 那就是32位 最大为2的32次方-1 也就是4294967295  也就是当-42  先转无符号数(也就是-1对应的是4294967295,依次类推)然后相加 
//10+(-42)=10+(4294967295-42+1)=4294967264

关于无符号数和有符号数可以参考这篇blog

理解有符号数和无符号数

在第一个输出表达式里,两个(负)整数相加并得到了期望的结果。

❗️ 在第二个输出表达式里,相加前首先把整数-42转换成无符号数。把负数转换成无符号数类似于直接给无符号数赋一个负值,结果等于这个负数加上无符号数的模。

当从无符号数中减去一个值时,不管这个值是不是无符号数,我们都必须确保结果不能是一个负值:

unsigned ul = 42,u2 = 10;
std::cout<< ul -u2<< std::endl; //正确:输出32
std::cout << u2 - ul<< std::endl;//正确:不过,结果是取模后的值  也是 10-42=10+(-42)=10+(4294967295-42+1)=4294967264

无符号数不会小于0这一事实同样关系到循环的写法。例如,在1.4.1节的练习(第11页)中需要写一个循环,通过控制变量递减的方式把从10到0的数字降序输出。这个循环可能类似于下面的形式:

for (int i = 10;i >= 0;--i)std:: cout<< i << std::endl;

可能你会觉得反正也不打算输出负数,可以用无符号数来重写这个循环。然而,这个不经意的改变却意味着死循环:

//错误:变量u永远也不会小于0,循环条件一直成立
for (unsigned u= 10; u >= 0;--u)std::cout<<u<< std::endl;

来看看当u等于0时发生了什么,这次迭代输出0,然后继续执行for语句里的表达式。表达式–u从u当中减去1,得到的结果-1并不满足无符号数的要求,此时像所有表示范围之外的其他数字一样,-1被自动地转换成一个合法的无符号数。假设 int类型占32位,则当u等于0时,–u的结果将会是4294967295。

一种解决的办法是,用while语句来代替for语句,因为前者让我们能够在输出变量之前(而非之后)先减去1:

unsigned u= 11;//确定要输出的最大数,从比它大1的数开始
while (u >0){//先减1,这样最后一次迭代时就会输出0--u;std::cout <<u<<std::endl;
}

改写后的循环先执行对循环控制变量减1的操作,这样最后一次迭代时,进入循环的u值为1。此时将其减1,则这次迭代输出的数就是0;下一次再检验循环条件时,u的值等于0而无法再进入循环。因为我们要先做减1的操作,所以初始化u的值应该比要输出的最大值大1。这里,u初始化为11,输出的最大数是10。

⭐️ 提示:切勿混用带符号类型和无符号类型

如果表达式里既有带符号类型又有无符号类型,当带符号类型取值为负时会出现异常结果,这是因为带符号数会自动地转换成无符号数。例如,在一个形如a*b的式子中,如果a =-1, b=-1,而且a和b都是int,则表达式的值显然为-1。然而,如果a是int,而b是unsigned,则结果须视在当前机器上int所占位数而定。在我们的环境里,结果是4294967295


🤙 好,结束!!撒花

现在回到开始的问题你会分析了不?

//练习2.3:读程序写结果。
unsigned u = 10,u2= 42;
//usigned 8位  
std:: cout << u2 - u<< std::endl;//32
std::cout <u - u2 << std:: endl;//10+4294967295-42+1=4294967264int i = 10,i2 =42;
//int 32位 4294967296-1=4294967295
std::cout<< i2 -i<< std::endl;  //32
std::cout << i - i2<< std::endl; //-32
std::cout << i - u<< std::endl; //0
std::cout << u- i<< std::endl;//0unsigned k1 = 42,k2 = 10;
std::cout<<k2-k1<<std::endl;//10+4294967295-42+1=4294967264
std::cout<<k1-k2<<std::endl;//32

🌈ok,完结~(●’◡’●) 看到这里 点个赞叭 (●’◡’●)

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

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

相关文章

牛客NC367 第K个n的排列【困难 dfs,全排列问题 Java/Go/PHP/C++】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/1595969179464e4c940a90b36abb3c54 思路 全排列问题本文提供的答案在力扣同一道题60. 排列序列&#xff0c;超时了但是截止文章发表日&#xff0c;牛客上是能通过全部测试用例的Java代码 import java.util.*;pu…

Redis - 优惠卷秒杀

场景分析 为了避免对数据库造成压力&#xff0c;我们在新增优惠卷的时候&#xff0c;可以将优惠卷的信息储存在Redis中&#xff0c;这样用户抢购的时候访问优惠卷信息&#xff0c;通过Redis读取信息。 抢购流程&#xff1a; 业务分析 既然在新增优惠卷的时候&#xff0c;我…

【c语言】了解指针,爱上指针(5)

了解指针&#xff0c;爱上指针&#xff08;5&#xff09; 回调函数qsort函数冒泡排序模拟实现qsort函数 回调函数 回调函数&#xff1a;就是一个通过函数指针调用的函数。 把函数的指针作为参数传给另一个函数&#xff0c;当这个指针被用来调用指向的函数时&#xff0c;此时被…

【Kotlin 一】Kotlin入门知识简介、变量声明、数字类型

1. Kotlin简介 Kotlin旨在解决 Java语言在编码效率和代码质量上存在的问题&#xff0c;并且与Java语言完全兼容。Kotlin通过简化语法、提供更强大的函数以及减少样本代码的编写&#xff0c;使开发者能够更高效地编写代码。Kotlin适用于Android、Web后端开发等多种场景 2.Kotl…

PHP获取文件路径getcwd()、__DIR__、__FILE__的区别

getcwd() getcwd() 是一个函数&#xff0c;它返回当前工作目录&#xff08;CWD&#xff09;的完整路径。当前工作目录是脚本开始执行时所在的目录&#xff0c;除非在脚本执行过程中通过 chdir() 函数进行了更改。 $cwd getcwd(); echo $cwd; // 输出当前工作目录的完整路径…

驱动编译报error: negative width in bit-field ‘<anonymous>’错误

错误如下图所示&#xff1a; 代码如下&#xff1a; 问题点&#xff1a;module_param的其他用户的权限参数上。 在Linux中&#xff0c;文件权限由读(r)、写(w)、执行(x)权限组成&#xff0c;分别对应数值4、2、1。 第一位0是占位符&#xff0c;在这里没有意义&#xff0c;因为…

ARM PMU - Performance Monitor Unit 用途和原理

From&#xff1a;程序员秘书 ARM Performance Monitor Unit (PMU) 是一种硬件组件&#xff0c;用于跟踪和计数系统中的底层硬件事件。集成在ARM架构的处理器中&#xff0c;用于监控和度量处理器及系统性能的关键指标。它对于性能分析、调试、能耗管理和优化软件性能至关重要。…

如何使用DotNet-MetaData识别.NET恶意软件源码文件元数据

关于DotNet-MetaData DotNet-MetaData是一款针对.NET恶意软件的安全分析工具&#xff0c;该工具专为蓝队研究人员设计&#xff0c;可以帮助广大研究人员轻松识别.NET恶意软件二进制源代码文件中的元数据。 工具架构 当前版本的DotNet-MetaData主要由以下两个部分组成&#xf…

java图书电子商务网站的设计与实现源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的图书电子商务网站的设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 图书电子商…

基于附带Attention机制的seq2seq模型架构实现英译法的案例

模型架构 先上图 我们这里选用GRU来实现该任务&#xff0c;因此上图的十个方框框都是GRU块&#xff0c;如第二张图&#xff0c;放第一张图主要是强调编码器的输出是作用在解码器每一次输入的观点&#xff0c;具体的详细流程图将在代码实现部分给出。 编码阶段 1. 准备工作…

【C++进阶】AVL树

0.前言 前面我们已经学习过二叉搜索树了&#xff0c;但如果我们是用二叉搜索树来封装map和set等关联式容器是有缺陷的&#xff0c;很可能会退化为单分支的情况&#xff0c;那样效率就极低了&#xff0c;那么有没有方法来弥补二叉搜索树的缺陷呢&#xff1f; 那么AVL树就出现了&…

6.小程序页面布局 - 账单明细

文章目录 1. 6.小程序页面布局 - 账单明细1.1. 竞品1.2. 布局分析1.3. 布局demo1.4. 页面实现-头部1.5. 账单明细1.5.1. 账单明细-竞品分析1.5.2. 账单明细-实现1.5.2.1. 账单明细-实现-mock数据1.5.2.2. 每日收支数据的聚合整理1.5.2.3. 页面scroll-view 1.6. TODO 1. 6.小程序…

java —— 封装、继承、接口和多态

一、封装 封装是将数据和操作这些数据的方法整合成一个类。在这个类中&#xff0c;用 private 修饰符将某些数据隐藏起来&#xff0c;只通过特定的方法实现这些数据的访问和修改&#xff0c;以此实现数据的完整和安全性。 封装的步骤&#xff1a; 二、继承 继承是指把子类共有…

Meta发布Chameleon模型预览,挑战多模态AI前沿

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【数据结构与算法】之堆的应用——堆排序及Top_K问题!

目录 1、堆排序 2、Top_K问题 3、完结散花 个人主页&#xff1a;秋风起&#xff0c;再归来~ 数据结构与算法 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c;律己则安&#xff01; 1、堆排序 对一个无序的数组…

03_前端三大件CSS

文章目录 CSS用于页面元素美化1.CSS引入1.1style方式1.2写入head中&#xff0c;通过写style然后进行标签选择器加载样式1.3外部样式表 2.CSS样式选择器2.1 元素选择器2.2 id选择器2.3 class选择器 3.CSS布局相关3.1 CSS浮动背景&#xff1a;先设计一些盒子因此&#xff0c;引出…

[图解]产品经理创新模式02改善信息流转

1 00:00:02,160 --> 00:00:04,000 第二种改进模式 2 00:00:04,010 --> 00:00:06,340 就是改善信息流转 3 00:00:06,550 --> 00:00:08,000 它是这样的 4 00:00:09,250 --> 00:00:11,290 当电脑系统越来越多的时候 5 00:00:11,300 --> 00:00:12,530 就会出现这…

linux centos stream 9 定时任务

定时任务,也称为计划任务,指在规定时间执行某项任务。在各操作系统中都有此功能,如Windows下的计划任务:定时关机等。 linux用户定时任务和系统定时任务是在Linux操作系统中用于自动执行特定任务的机制。它们基于cron(cron daemon)服务来完成的。 cron是linux系统中以后台…

Hive运行错误

Hive 文章目录 Hive错误日志错误SessionHiveMetaStoreClientql.Driver: FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTaskerror: Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster Please check …

DOS学习-目录与文件应用操作经典案例-type

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一.前言 二.使用 三.案例 1. 查看文本文件内容 2. 同时查看多个文本文件内容 3. 合并文…