C++ 系列 第五篇 C++ 算术运算符及类型转换

系列文章

C++ 系列 前篇 为什么学习C++ 及学习计划-CSDN博客

C++ 系列 第一篇 开发环境搭建(WSL 方向)-CSDN博客

C++ 系列 第二篇 你真的了解C++吗?本篇带你走进C++的世界-CSDN博客

C++ 系列 第三篇 C++程序的基本结构-CSDN博客

C++ 系列 第四篇 C++ 数据类型上篇—基本类型-CSDN博客 

前言

        我们上一篇总结了C++的基本类型,涉及整形和浮点型,总的来说都是数值类型,在实际编程中一定会碰到数值相关的算术运行。所以这一篇我们总结下C++的算术运算,最主要的是不同类型 的整形或浮点型进行算术运算时候的一些隐式类型转换,虽然是一些基本得知识,但真的是容易被遗忘或者编程时被忽视的点,相信有足够编程经历的程序猿们多少都被类型隐式转换坑过。

C++运算符

        C++使用运算符来运算。提供了几种运算符来完成5种基本的算术计算,分别是 加法(+)、减法(-)、乘法(*)、除法(、)以及求模(%), 每种运算符都使用两个值(操作数)来计算结果,运算符及操作数构成了表达式,变量和常量都可以用作操作数。C++中这些算术运算符的使用方式及限制和C 语言是一致的。

        + 运算符对操作数执行加法运算。例如,4+20 等于 24。

        - 运算符从第一个数中减去第二个数。例如,12-3 等于 9。

        * 运算符将操作数相乘。例如,28 * 4 等于 112。

        / 运算符用第一个数除以第二个数。例如,1000 / 5等于200。如果两个操作数都是整数,则结果为商的整数部分。例如,17 / 3 等于 5,小数部分被丢弃。

        % 运算符求模。也就是说,它生成第一个数除以第二个数后的余数。例如,19 % 6 为 1,因为 19是 6 的 3 倍余 1。两个操作数必须都是整型,将该运算符用于浮点数将导致编译错误。

运算符的优先级

示例1:不同优先级操作符

        int value=3 + 4 * 5;  结果是35还是23呢?

        当多个运算符可用于同一个操作数时,C++使用优先级规则来决定首先使用哪个运算符。算术运算符遵循通常的代数优先级,先乘除,后加减。因此 3+4*5 指的是 3+(4*5),而不是(3+4)*5,结果为 23,而不是 35。当然,可以使用括号来执行自己定义的优先级。

        乘法(*)、除法(/)和 取模(%)优先级相同。同样,加和减的优先级也相同,但比乘除低。

示例2:同优先级操作符

        float value = 120 / 4 *5; 结果是150 还是6呢?

        运算符 "/" 和 "*" 的优先级相同,因此优先级本身并不能指出程序究竟是先计算120除以 4.还是先计算4乘以5。因为第一种选择得到的结果是150,而第二种选择的结果是6,因此选择十分重要。

        当两个运算符的优先级相同时,C++将看操作数的结合性是从左到右,还是从右到左。从左到右的结合性意味着如果两个优先级相同的运算符被同时用于同一个操作数,则首先应用左侧的运算符。从右到左的结合性则首先应用右侧的运算符。C++ 及C 语言中,乘除都是从左到右结合的。这说明应当先对4使用左侧的运算符。也就是说,用120 除以 4,得到的结果为 30,然后再乘以 5,结果为 150。注意,仅当两个运算符被用于同一个操作数时,优先级和结合性规则才有效。

示例3:有优先级和结合性是否就能确保结果?        

        int value = 20 * 5 + 24 * 6

        运算符优先级表明了两点:程序必须在做加法之前计算20 * 5,必须在做加法之前计算24 * 6。但优先级和结合性都没有指出应先计算哪个乘法。读者可能认为,结合性表明应先做左侧的乘法,但是在这种情况下,两个*运算符并没有用于同一个操作数,所以该规则不适用。事实上,C++把这个问题留给了实现,让编译器来决定在系统中的最佳顺序。对于这个例子来说,两种顺序的结果是一样的。

        但是也有两种顺序结果不同的情况,比如后边章节会总结的递增运算符,如下例子中vlaue4 就是一个极端的例子。

类型转换 

        C++及C 语言丰富的类型允许根据需求选择不同的类型,这也使计算机的操作更复杂。例如,将两个 short 值相加涉及到的硬件编译指令可能会与将两个 long 值相加不同。由于有 11 种整型和 3 种浮点类型,因此计算机需要处理大量不同的情况,尤其是对不同的类型进行运算时。为处理这种潜在的混乱,C++及C语言在以下情况中会自动执行类型转换:

        1、将一种算术类型的值赋给另一种算术类型的变量时,将对值进行转换;

        2、表达式中包含不同的类型时,将对值进行转换;

        3、将参数传递给函数时,将对值进行转换。   

        4、使用 和 函数返回类型不同的类型变量接受返回值,将对值进行转换。(这个也是实际编程中经常会碰到的bug)  

初始化及赋值时的类型转换 

        C++允许将一种类型的值赋给另一种类型的变量。这样做时,值将被转换为接受变量的类型,如下示例,long 类型的值赋值给int 型时,转换为了ini 型,double赋值给int 型时,也转换为了int型。

         将一个值赋给值取值范围更大的类型通常不会导致什么问题。例如,将 short 值赋给long 变量并不会改变这个值,只是占用的字节更多而已。然而,将一个很大的long值(如2111222333)赋给float变量将降低精度。因为 float 只有6 位有效数字,因此这个值将被四舍五入为 2.11122E9。因此,有些转换是安全的,有些则会带来麻烦。如下表列出了可能出现的转换问题。

 以{}初始化时进行的转换

        C++11 将使用大括号的初始化称为列表初始化,因为这种初始化常用于给复杂的数据类型提供值列表。它对类型转换的要求更严格。具体地说,列表初始化不允许缩窄(narrowing),即变量的类型可能无法表示赋给它的值。例如,不允许将浮点型转换为整型。将整型转换为浮点型被允许,条件是编译器知道目标变量能够正确地存储赋给它的值。例如,可将 long 变量初始化为 int 值,因为 long 总是至少与 int 一样长;相反方向的转换也可能被允许,只要 int 变量能够存储赋给它的 long 常。

表达式中的转换 

        当同一个表达式中包含两种不同的类型时,C++将执行两种自动转换:首先,一些类型在出现时便会自动转换;其次,有些类型在与其他类型同时出现在表达式中时将被转换。

        先来看看自动转换。在计算表达式时,C++将bool、char、unsigned charsigned char 和 short 值转换为int。这些转换被称为整型提升(integral promotion)。

        我们还是写一个小用例来说明问题,如下我们声明了两个short类型的变量a和b,并打印它们的大小(以字节为单位)。然后,我们将a和b相加,并打印相加后的结果的大小。

        当运行这个程序时,会发现a和b的大小都是 2 字节。然而,当我们将它们相加后,实际相加后结果并不需要int来存储,结果的大小却是 4 字节,这就证明了short类型在表达式计算中被自动提升为int类型。

同样,wchar_t 被提升成为下列类型中第一个宽度足够存储wchar_t取值范围的类型:int、unsigned int、long 或unsigned long.

        再来看下不同类型进行算术运算时,进行的一些转换。

        当运算涉及两种类型时,较小的类型将被转换为较大的类型。例如,用 9.0 除以 5。由于9.0 的类型为 double,因此程序在用5除之前,将 5 转换为 double 类型。运算时的转换,符合以下规律:

        1、如果有一个操作数的类型是 long double,则将另一个操作数转换为 long double。

        2、否则,如果有一个操作数的类型是double,则将另一个操作数转换为double。

        3、否则,如果有一个操作数的类型是 float,则将另一个操作数转换为float。

        4、否则,说明操作数都是整型,因此执行整型提升。

        5、在这种情况下,如果两个操作数都是有符号或无符号的,且其中一个操作数的级别比另一个低,则转换为级别高的类型。这里所说的级别就是 比如long 级别比int 高。

        6、如果一个操作数为有符号的,另一个操作数为无符号的,且无符号操作数的级别比有符号操作数高,则将有符号操作数转换为无符号操作数所属的类型。

        7、否则,如果有符号类型可表示无符号类型的所有可能取值,则将无符号操作数转换为有符号操作数所属的类型。

        8、否则,将两个操作数都转换为有符号类型的无符号版本。

函数涉及的转换

        传递参数时的类型转换通常由C++函数原型控制。函数返回值,则由 接受返回值的变量类型进行确认,在日常代码工程中,经常能看到 有人 封装的一个函数 返回 -1 (int型), 但是 使用的人,没注意看,用的是无符号int 定义的变量 进行接受的,就会导致 整个逻辑判断出错,一定要当心。

强制类型转换

        C++还允许通过强制类型转换机制显式地进行类型转换。强制类型转换的格式有两种。我们还是用实例说明问题,如下示例中, a 是short 型, 可以 使用(typename) variable 或者 typename (variable) 的方式进行强制类型转换,同时强制类型转换不会修改原有变量的类型,而是创建一个新的、指定类型的值,可以在表达式中使用这个值。

        (typename) variable 或者 typename (variable)  第一种格式来自C语言,第二种格式是纯粹的 C++。新格式的想法是,要让强制类型转换就像是函数调用。

        当然C++ 认为C语言的强制转换太危险,所以还增加了其他的约束力更强的强制类型转换,有4中,分别如下,我们这里只做简单 陈述,后边涉及到再展开讨论:

  1. static_cast:用于非多态类型之间的转换,如基本数据类型之间的转换,以及具有继承关系的类型之间的转换。但它不能用于将 const 或 volatile 限定符添加或删除。

  2. dynamic_cast:用于具有继承关系的类型之间的转换,它在运行时进行类型检查,只能用于具有虚函数的类(多态类型)。它可以用于将指向基类的指针或引用转换为指向派生类的指针或引用,或者将指向派生类的指针或引用转换为指向基类的指针或引用。如果转换失败,dynamic_cast 运算符将返回一个空指针(对于指针类型)或引发一个 std::bad_cast 异常(对于引用类型)。

  3. const_cast:用于添加或删除 const 或 volatile 限定符。它可以用于将常量对象转换为非常量对象,或者将非常量对象转换为常量对象。但是,const_cast 并不能用于修改本来就是常量的对象,或者用于修改指向常量对象的指针。

  4. reinterpret_cast:用于不同类型之间的强制类型转换,它可以将任意类型的指针或引用转换为其他类型的指针或引用,甚至可以将指针转换为整数类型,或者将整数类型转换为指针。但是,使用 reinterpret_cast 进行类型转换时需要非常小心,因为它会绕过编译器的类型检查,可能导致未定义的行为。

总结

        C++使用运算符来提供对数字类型的算术运算:加、减、乘、除和求模。当两个运算符对同一个操作数进行操作时,C++的优先级和结合性规则可以确定先执行哪种操作。

        对变量赋值、在运算中使用不同类型、使用强制类型转换时,C++将把值从一种类型转换为另一种类型。很多类型转换都是“安全的”,即可以在不损失和改变数据的情况下完成转换。例如,可以把 int 值转换为 long 值,而不会出现任何问题。对于其他一些转换,如将浮点类型转换为整型,则需要更加小心。

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

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

相关文章

94.STM32外部中断

目录 1.什么是 NVIC? 2.NVIC寄存器 3.中断优先级 4.NVIC的配置 设置中断分组​编辑 配置某一个中断的优先级 5.什么是EXTI 6.EXTI和NVIC之间的关系 7.SYSCFG 的介绍 1.什么是 NVIC? NVIC是一种中断控制器,主要用于处理 ARM Cort…

自动化框架错误排查:本地全通过,pipline上大部分报错

现象: 最近经过一次切环境和验证码部分的代码重构,果不其然,我们的自动化框架就出错了 我在本地修改调试,并在堡垒机上全部跑过 但在pipline上则大部分报错 进一步排查 这么多case报错,而且报错log都一模一样,推断是底层出错 我在堡垒机上使用命令行来跑case,发现与…

时序预测 | Python实现GA-TCN-LSTM遗传算法-时间卷积神经网络-长短期记忆网络时间序列预测

时序预测 | Python实现GA-TCN-LSTM遗传算法-时间卷积神经网络-长短期记忆网络时间序列预测 目录 时序预测 | Python实现GA-TCN-LSTM遗传算法-时间卷积神经网络-长短期记忆网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 使用先进的机器学习技术和优化算法…

【C++ regex】C++正则表达式

文章目录 前言一、正则表达式是什么&#xff1f;二、<regex>库的基础使用2.1 第一个示例2.1 <regex>库的函数详解std::regex_matchstd::regex_searchregex_search 和 regex_match 的区别std::regex_replacestd::regex_iterator 和 std::sregex_iterator&#xff1a…

MacBook Pro 安装Nacos【超详细图解】

目录 一、安装Nacos 二、启动nacos 三、进入可视化界面 因项目用到nacos&#xff0c;所以需要装一个&#xff0c;顺便写篇文章记录 一、安装Nacos 前往官网下载&#xff1a;Nacos官网homehttps://nacos.io/zh-cn/ # 解压 unzip nacos-server-2.3.0.zip 二、启动nacos …

Collection集合的遍历方式-迭代器,增强for循环,Lambda

集合体系概述 Collection是单列集合的祖宗&#xff0c;它规定的方法&#xff08;功能&#xff09;是全部单列集合都会继承的 public class Work1 {public static void main(String[] args) {//简单认识一下Collection集合的特点ArrayList<String> list new ArrayList&…

【Vue2】Vue的介绍与Vue的第一个实例

文章目录 前言一、为什么要学习Vue二、什么是Vue1.什么是构建用户界面2.什么是渐进式Vue的两种开发方式&#xff1a; 3.什么是框架 三、创建Vue实例四、插值表达式 {{}}1.作用&#xff1a;利用表达式进行插值&#xff0c;渲染到页面中2.语法3.错误用法 五、响应式特性1.什么是响…

mysql中删除数据后,新增数据时id会跳跃,主键自增id不连续

引言&#xff1a; 在使用MySQL数据库时&#xff0c;有时候我们需要删除某些记录&#xff0c;但是删除记录后可能会导致表中的id不再连续排序。 如何实现删除记录后让id重新排序的功能。 如图&#xff1a; 删除数据后&#xff0c;中间的id不会自动连续。 下面有两种方法进行重…

医院绩效系统源码:基础数据管理、核算方法和分配规则、KPI评分公式等功能

医院绩效管理系统源码&#xff0c;医院绩效管理数据采集的自动化和绩效评估数字化 医院绩效管理系统以国家医院绩效管理考核政策法规为依据&#xff0c;结合医院管理实践&#xff0c;以经济管理指标为核心&#xff0c;医疗质量、安全、效率、效益管理为重点&#xff0c;特别强调…

unity3d模型中缺失animation

在 模型的Rig-Animationtype 设置成Legacy https://tieba.baidu.com/p/2293580178

OWASP SAMM 软件保障成熟度模型

软件保障成熟度模型 我们的使命是为您提供一种有效且可衡量的方式来分析和改进您的安全开发生命周期。 SAMM 支持完整的软件生命周期&#xff0c;并且与技术和流程无关。我们构建的 SAMM 本质上是不断发展和风险驱动的&#xff0c;因为没有一种单一的配方适用于所有组织。奥瓦…

JVM——垃圾回收器(G1,JDK9默认为G1垃圾回收器)

1.G1垃圾回收器 JDK9之后默认的垃圾回收器是G1&#xff08;Garbage First&#xff09;垃圾回收器。 Parallel Scavenge关注吞吐量&#xff0c;允许用户设置最大暂停时间 &#xff0c;但是会减少年轻代可用空间的大小。 CMS关注暂停时间&#xff0c;但是吞吐量方面会下降。 而G1…

【C语言】扫雷小游戏初学者版

成功的秘诀就是每天都比别人多努力一点。 今天给大家带来一款非常经典的小游戏——扫雷的实现和讲解 这里是目录 前言整体框架1.打印菜单2.创建二维数组3.初始化棋盘4.打印棋盘5.布置棋盘中的雷6.排查雷和统计雷总体代码test.cgame.cgame.h 进阶&#xff08;递归展开&#xff0…

CityEngine2023 shp数据城市与路网三维模型并导入UE5

目录 0 引言1 城市和道路数据获取1.1 常用方法1.2 OSM数据获取1.3 OSM数据格式1.3.1 所有格式1.3.2 Shapefile格式 2 实践2.1 导入数据&#xff08;.shp&#xff09;2.2 构建三维模型2.3 将模型导入UE5 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xf…

手机传输数据到电脑该怎么操作?安卓、苹果都可以这样操作

安卓手机 你知道安卓手机传输数据到电脑的方法有哪些吗&#xff1f;下面我们就一起来看一看可以使用的一些方法。 采用 USB 数据线 这个方法应该是我们生活中较为常见的方法了&#xff0c;我们只需要使用手机的充电线&#xff0c;将其连接到电脑上&#xff0c;然后手机可能会…

Motion Plan之轨迹生成笔记 (2)

Motion Plan之搜索算法笔记 Motion Plan之基于采样的路径规划算法笔记 Motion Plan之带动力学约束路径搜索 什么是基于优化的轨迹生成 Optimization-Based Trajectory Planning&#xff08;基于优化的轨迹规划&#xff09;是一种常用的方法&#xff0c;用于生成自动化系统&am…

2.4 API 开发和集成

文章目录 API 开发和集成API 的概念和作用API 开发基础API 集成API 鉴权和安全API 文档和测试微服务和 API 网关云服务和 API 集成未来趋势和发展实验实验一&#xff1a; 通过api post方式传入 json实验二&#xff1a;通过api将所需数据传入 API 开发和集成 API 的概念和作用介…

StarRocks上新,“One Data、All Analytics”还有多远?

K.K在《未来十二大趋势》中认为&#xff0c;我们正处于一个数据流动的时代。商业乃数据之商业。归根结底&#xff0c;你在处理的都是数据。 的确&#xff0c;当数据成为新的核心生产要素之际&#xff0c;数据分析就犹如最重要的生产工具之一&#xff0c;决定着企业在数字化时代…

Python爬虫超详细讲解(零基础入门,包教包会)

先看后赞&#xff0c;养成习惯。 点赞收藏&#xff0c;人生辉煌。 讲解我们的爬虫之前&#xff0c;先概述关于爬虫的简单概念&#xff08;毕竟是零基础教程&#xff09; 爬虫 网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff09;就是模拟浏览器发送网络…