【C++】 算术操作符与数据类型溢出详解
文章目录
- 💯前言
- 💯C++ 算术操作符详解
- 基本算术操作符
- 整数除法与取模行为
- 类型转换在算术运算中的作用
- 自增与自减操作符
- 💯数值溢出:当值超出类型范围时
- 数据类型的取值范围
- 正向与负向溢出
- 避免数值溢出的方法
- 💯`char` 类型与 ASCII 表的关系
- `char` 的本质
- 如何输出整数值和字符值
- 示例:`char` 赋值整数与字符
- `char a = 127` 是否规范?
- 💯取模操作与负数的处理
- 取模运算符 `%`
- 工作机制
- 规则总结
- 示例
- 如何确保结果为正?
- 💯编程建议
- 💯小结
💯前言
- 在程序设计中,理解算术操作符的机制以及数据类型的行为是至关重要的,尤其是在涉及不同类型的数据运算时。本文深入探讨了 C++ 中的算术操作符、数值溢出和类型转换 的细节,结合实际编程中的典型疑问,为您提供理论与实践相结合的视角。本文将涵盖基本算术操作、类型转换、负数取模、数值溢出,以及字符类型(
char
)与ASCII
编码的细节。
C++ 参考手册
💯C++ 算术操作符详解
基本算术操作符
C++ 提供了一组基本的算术操作符,用于执行常见的数学运算,主要包括:
+
:加法,用于将两个操作数相加。-
:减法,用于计算两个操作数的差值。*
:乘法,用于计算两个操作数的积。/
:除法,用于将第一个操作数除以第二个操作数。%
:取模,用于计算两个整数的余数。
整数除法与取模行为
-
整数除法 (
/
):当两个操作数都是整数类型时,结果也是整数,小数部分将被舍弃。例如:int b = 2; double d = 7 / 2; // 结果是 3,因为小数部分被舍弃
在上述代码中,虽然变量
d
被定义为double
类型,但7
和2
均为int
类型,因此7 / 2
的结果为整数3
,随后赋值给d
,因此d
的值为3.0
。对于正确处理浮点结果,至少需要确保一个操作数为浮点类型。例如:
double d = 7.0 / 2; // 结果为 3.5,因为 7.0 是 double 类型
-
取模操作 (
%
) 只能用于整数类型。
-
如果操作数是浮点数类型,必须使用
<cmath>
库中的fmod
函数来计算余数。例如:#include <cmath> double result = fmod(10.5, 3.2); // 结果是 0.9
类型转换在算术运算中的作用
在算术运算中,C++ 通常会对不同类型的操作数进行隐式类型转换,以确保运算的精度和一致性。例如:
- 当
int
与double
进行运算时,int
会被自动提升为double
,然后进行浮点运算。
在上述代码中,double d = 6.0 / 4; // 结果是 1.5,因为 6.0 是 double,4 被提升为 double
6.0
是double
类型,而4
是int
,C++ 会将4
隐式提升为4.0
,进而进行浮点除法,最终得到1.5
。
自增与自减操作符
C++ 中的 ++
和 --
操作符用于对变量进行自增和自减操作:
- 前置形式 (
++a
或--a
):先对变量的值进行改变,再使用改变后的值。 - 后置形式 (
a++
或a--
):先使用变量的原始值,再对其进行改变。
例如:
int a = 5;
int b = ++a; // b = 6, a = 6
int c = a++; // c = 6, a = 7
在复杂的表达式或循环中,前置与后置自增/自减操作符的使用对结果有很大的影响,因此应当谨慎使用。
💯数值溢出:当值超出类型范围时
在 C++ 中,数值溢出指的是当计算结果超出变量数据类型所能表示的范围时,结果可能变得无法预测或与预期不符。数值溢出在处理较小的数据类型(如 char
或 short
)时尤为常见。
数据类型的取值范围
每种数据类型在 C++ 中都有相应的取值范围,这与它们的存储大小直接相关。例如:
char
类型:通常占用 1 个字节,有符号的char
范围为-128
到127
。int
类型:通常占用 4 个字节,范围为-2,147,483,648
到2,147,483,647
(具体范围取决于编译器和平台)。
当计算结果超出这些取值范围时,便会发生溢出。例如:
#include <iostream>
using namespace std;
int main()
{char a = 127; char b = a + 1; cout << (int)b << endl; //-128return 0;
}
在上述代码中,a
的初始值为 char
类型的最大值 127
,再加 1
会导致溢出,最终结果从 -128
开始循环。
正向与负向溢出
- 正向溢出:当一个有符号类型的值达到最大值再加一时,结果会从最小值重新开始。例如,
char a = 127; a += 1;
的结果是-128
。 - 负向溢出:当一个有符号类型的值达到最小值再减一时,结果会从最大值重新开始。例如,
char a = -128; a -= 1;
的结果是127
。
这些现象遵循二进制补码的规则,溢出的结果会在数值范围内循环,这在某些算法中可能导致严重的逻辑错误,特别是在数值计算和边界条件处理时。
避免数值溢出的方法
- 使用更大的数据类型:如果运算结果可能超出当前类型的范围,应使用更大范围的数据类型,如
long
或long long
。 - 手动检查溢出风险:在执行运算前,可以对操作数进行判断,以确保不会发生溢出。
- 使用专门的库或工具:一些库(如
SafeInt
)或编译器选项能够检测并避免溢出,从而保障程序的正确性。
💯char
类型与 ASCII 表的关系
char
的本质
在 C++ 中,char
类型实际上是一个整数类型,用于存储字符的 ASCII 编码值。char
通常占用 1 个字节,可以表示 -128
到 127
(有符号)或 0
到 255
(无符号)的整数。
当给 char
赋值一个整数时,实际上是将该整数视为 ASCII 码。例如:
char c = 65;
std::cout << c << std::endl; // 输出:A
在上述代码中,65
是 ASCII 表中字符 A
的编码,因此输出为 A
。
如何输出整数值和字符值
- 作为字符输出:直接输出
char
类型时,会显示其对应的 ASCII 字符。 - 作为整数输出:如果希望查看
char
实际存储的整数值,可以将其强制类型转换为int
。char c = 'A'; std::cout << (int)c << std::endl; // 输出:65
示例:char
赋值整数与字符
考虑以下代码:
char a = 127;
a += 1;
std::cout << (int)a << std::endl; // 输出:-128
在上述代码中,a
被赋值为整数 127
,表示 char
的最大正值。当 a += 1
时,发生溢出,结果为 -128
。这是因为 char
类型按照二进制补码表示数值,从最大值溢出到最小值。
char a = 127
是否规范?
在 char a = 127;
中,127
是一个整数值,不需要加引号。char
类型存储的是整数值,这个值会在输出时按照 ASCII 编码对应的字符显示。例如,char a = 65;
会输出字符 A
。在上述例子中,127
是 char
类型的最大值,当 a += 1
后发生溢出,结果是 -128
。因此,直接给 char
赋整数值是合法的,不需要加引号。
💯取模操作与负数的处理
取模运算符 %
在 C++ 中,取模运算符 %
用于计算两个整数相除后的余数。然而,当操作数中存在负数时,其行为可能并不符合直觉。
工作机制
取模运算基于整数除法,通过计算商并求得余数。
- 具体公式为:
a % b = a - (a / b) * b
。 - 当有负数时,
a / b
的商向零取整,余数的符号由被除数决定。 - 例如,
-7 % 3
中,-7 / 3
的商为-2
(向零取整),余数的计算为:-7 - (-2 * 3) = -7 + 6 = -1
。
规则总结
- 结果的符号由被除数(左操作数)决定。
- 例如:
-7 % 3
的结果是-1
,因为-7
是负数,结果的符号也为负。 - 类似地,
7 % -3
的结果是1
,因为7
是正数。
- 例如:
示例
int a = -7;
int b = 3;
std::cout << a % b << std::endl; // 输出:-1
在上述代码中,-7 / 3
的商为 -2
(向零取整),余数为 -1
。在取模运算中,符号遵循被除数的符号。
如何确保结果为正?
在某些情况下,我们可能希望取模结果始终为正数,可以使用以下公式来实现:
int result = ((a % b) + b) % b;
这个公式可以确保无论 a
和 b
的符号如何,结果始终为非负值。
💯编程建议
- 注意类型范围:在进行加法、乘法等操作时,确保结果不会超出当前数据类型的范围,以避免不必要的溢出。
- 选择合适的数据类型:根据预期的数据规模选择适合的数据类型(例如
long long
而非int
),以确保结果的正确性。 - 明确取模运算的行为:特别是在涉及负数时,应仔细理解取模运算的符号规则,必要时通过调整公式来获得预期的结果。
💯小结
算术操作符和类型转换:整数运算结果是整数,小数部分会被舍弃,而浮点运算可以保留精度。- 数值溢出:当操作数超出其类型范围时,会发生溢出,结果会按二进制补码规则循环。
char
类型与整数赋值:char
本质上是一个整数类型,赋值整数时会存储其对应的 ASCII 码值。- 负数取模:取模结果的符号由被除数决定,负数取模时可能需要调整公式以确保结果为正。
相关文章:

【C++】 算术操作符与数据类型溢出详解
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯C 算术操作符详解基本算术操作符整数除法与取模行为类型转换在算术运算中的作用自增与自减操作符 💯数值溢出:当值超出类型范围时数据类型的取值范围…...

柔性芯片:实现万物互联的催化剂
物联网 (IoT) 市场已经非常成熟,麦肯锡预测,物联网将再创高峰,到 2030 年将达到 12.5 万亿美元的估值。然而,万物互联 (IoE) 的愿景尚未实现,即由数十亿台智能互联设备组成,提供大规模洞察和效率。 究竟是…...

FFmpeg 简介与编译
1. ffmpeg 简介: FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移…...

低代码与微服务融合在医疗集团中的补充应用探究
摘要 本论文深入探讨了低代码与微服务融合在医疗系统集群中的应用。分析了其优势,包括提高开发效率、降低技术门槛、灵活适应需求变化和易于维护扩展等;阐述了面临的挑战,如数据安全与隐私保护、技术应用复杂性等;并展望了其在医…...
速盾:高防cdn的搜索引擎回源是什么?
高防CDN(Content Delivery Network)是一种用于加速网站访问速度和增加安全性的服务,它通过将静态和动态内容缓存在全球分布的服务器上,从而将用户请求的响应时间降至最低,并提供有效的防御攻击的能力。在实际使用过程中…...

减少电路和配电系统谐波的五种方法
K 级变压器 ANSI 标准 C57.110-1986 定义了 K 系数来评估电路消耗多少谐波电流并确定该谐波电流的热效应。根据电路 K 系数,变压器按 K 等级制造。值得注意的是,K 级变压器不会减少谐波。K 等级表示变压器承受谐波有害影响的相对能力。K级变压器增加了铁…...

基于Java Springboot Vue3图书管理系统
一、作品包含 源码数据库设计文档万字全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue3、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA 数据库&#x…...

vue-cli项目质量约束配置
同步发布于我的网站 🚀 package.json scriptslint-stageddevDependencies git-hooksno-eslintdevDependencies - scssdevDependencies - lessengines pre-commit.eslintrc.js.stylelintrc scssless vue.config.jsREADME.md package.json scripts "scripts&…...

第七课 Unity编辑器创建的资源优化_UI篇(UGUI)
上期我们学习了简单的Scene优化,接下来我们继续编辑器创建资源的UGUI优化 UI篇(UGUI) 优化UGUI应从哪些方面入手? 可以从CPU和GPU两方面考虑,CPU方面,避免触发或减少Canvas的Rebuild和Rebatch,…...
【docker】docker build上下文
什么是 Docker Build 上下文? 在 Docker 中,构建上下文(Build Context) 是指在执行 docker build 命令时,Docker 会发送给 Docker 引擎的所有文件和目录的集合。构建上下文包含了 Dockerfile 和用于构建镜像的所有文件…...
ESLint 配置文件全解析:格式、层叠与扩展(3)
配置文件系统处于一个更新期,存在两套配置文件系统,旧的配置文件系统适用于 v9.0.0 之前的版本,而新的配置文件系统适用于 v9.0.0之后的版本,但是目前还处于 v8.x.x 的大版本。 配置文件格式 在 ESLint 中,支持如下格…...

org.apache.commons.lang3包下的StringUtils工具类的使用
前言 相信平时在写项目的时候,一定使用到StringUtils.isEmpty();StringUtils.isBlank();但是你真的了解他们吗? 也许你两个都不知道,也许你除了isEmpty/isNotEmpty/isNotBlank/isBlank外,并不知道还有isAnyEmpty/isNon…...

HarmonyOS4+NEXT星河版入门与项目实战(23)------组件转场动画
文章目录 1、控件图解2、案例实现1、代码实现2、代码解释3、实现效果4、总结1、控件图解 这里我们用一张完整的图来汇整 组件转场动画的用法格式、属性和事件,如下所示: 2、案例实现 这里我们对上一节小鱼游戏进行改造,让小鱼在游戏开始的时候增加一个转场动画,让小鱼自…...

十一、快速入门go语言之接口和反射
文章目录 接口:one: 接口基础:two: 接口类型断言和空接口:star2: 空接口实现存储不同数据类型的切片/数组:star2: 复制切片到空接口切片:star2: 类型断言 反射 📅 2024年5月9日 📦 使用版本为1.21.5 接口 十、Java类的封装和继承、多态 - 七点半的菜市…...

智能化图书馆导航系统方案之系统架构与核心功能设计
hello~这里是维小帮,点击文章最下方获取图书馆导航系统解决方案!如有项目需求和技术交流欢迎大家私聊我们~撒花! 针对传统图书馆在图书查找困难、座位紧张、空间导航不便方面的问题,本文深入剖析了基于高精度定位、3D建模、图书搜…...
学习嵩山版《Java 开发手册》:编程规约 - 命名风格(P13 ~ P14)
概述 《Java 开发手册》是阿里巴巴集团技术团队的集体智慧结晶和经验总结,他旨在提升开发效率和代码质量 《Java 开发手册》是一本极具价值的 Java 开发规范指南,对于提升开发者的综合素质和代码质量具有重要意义 学习《Java 开发手册》是一个提升 Jav…...

Qt关于padding设置不起作用的的解决办法
观察以下的代码: MyWidget::MyWidget(QWidget *parent): QWidget{parent},m_btn(new QToolButton(this)) {this->setFixedSize(500,500);m_btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);m_btn->setIcon(QIcon("F:tabIcon/person-white.s…...
Golang教程第10篇(语言循环语句-语言循环嵌套)
Go 语言循环嵌套 Go 语言循环语句Go 语言循环语句 Go 语言允许用户在循环内使用循环。接下来我们将为大家介绍嵌套循环的使用。 语法 以下为 Go 语言嵌套循环的格式: for [condition | ( init; condition; increment ) | Range] {for [condition | ( init; con…...
Python Web 开发:FastAPI 入门实战 —— HTTP 基础与 RESTful API 设计
Python Web 开发:FastAPI 入门实战 —— HTTP 基础与 RESTful API 设计 目录 🚀 HTTP 协议概述🌐 HTTP 请求与响应的工作原理🛠️ RESTful API 设计理念🗂️ JSON 格式数据的传输与解析 1. 🚀 HTTP 协议概…...

uniapp实现组件竖版菜单
社区图片页面 scroll-view scroll-view | uni-app官网 (dcloud.net.cn) 可滚动视图区域。用于区域滚动。 需注意在webview渲染的页面中,区域滚动的性能不及页面滚动。 <template><view class"pics"><scroll-view class"left"…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...