C++ 中有符号数与无符号数的隐式转换与运算陷阱

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

#include <iostream>int main() {unsigned u = 10, u2 = 42;std::cout << "u2 - u  =" << u2 - u << std::endl;std::cout << "u  - u2 =" << u - u2 << std::endl;int i = 10, i2 = 42;std::cout << "i2 - i  =" << i2 - i << std::endl;std::cout << "i  - i2 =" << i - i2 << std::endl;u = 42;i = 10;std::cout << "i  - u  =" << i - u << std::endl;std::cout << "u  - i  =" << u - i << std::endl;u = 10;i = -42;std::cout << "i  - i  =" << i + i << std::endl;  // prints -84std::cout << "u  - i  =" << u + i << std::endl;  // if 32-bit ints, prints 4294967264i = 10;std::cout << "good" << std::endl;while (i >= 0) {std::cout << i << " ";--i;}std::cout << std::endl;for (int i = 10; i >= 0; --i)std::cout << i << " ";std::cout << std::endl;for (unsigned u = 0; u <= 10; ++u)std::cout << u << " ";  // prints 0 . . . 10std::cout << std::endl;/* NOTE: the condition in the following loopwill run indefinitely// WRONG: u can never be less than 0; the condition will always succeedfor (unsigned u = 10; u >= 0; --u)std::cout << u << std::endl;
*/u = 11; // start the loop one past the first element we want to printwhile (u > 0) {--u;        // decrement first, so that the last iteration will print 0std::cout << u << " ";}std::cout << std::endl;// be wary of comparing ints and unsignedu = 10;i = -42;if (i < u)               // false: i is converted to unsignedstd::cout << i << std::endl;elsestd::cout << u << std::endl;   // prints 10u = 42;u2 = 10;std::cout << "u  - u2  =" << u - u2 << std::endl; // ok: result is 32std::cout << "u2 - u   =" << u2 - u << std::endl; // ok: but the result will wrap around
}

输出:

u2 - u  =32
u  - u2 =4294967264
i2 - i  =32
i  - i2 =-32
i  - u  =4294967264
u  - i  =32
i  - i  =-84
u  - i  =4294967264
good
10 9 8 7 6 5 4 3 2 1 0 
10 9 8 7 6 5 4 3 2 1 0 
0 1 2 3 4 5 6 7 8 9 10 
10 9 8 7 6 5 4 3 2 1 0 
10
u  - u2  =32
u2 - u   =4294967264

有符号数与无符号数的转换规则

  1. 隐式转换:当有符号数与无符号数一起使用时,有符号数会被隐式转换为无符号数。这可能导致负数转换为一个很大的正数。

    int a = -1;
    unsigned b = 1;
    if (a < b) {// 实际上a被转换为无符号数,变成了一个很大的正数
    }
    
  2. 显式转换:可以使用类型转换运算符显式地将一个有符号数转换为无符号数,或反之。需要注意的是,这样的转换可能会导致意料之外的结果。

    int a = -42;
    unsigned b = static_cast<unsigned>(a); // b现在是一个很大的正数
    

无符号数的特性

  1. 零或正数:无符号数总是表示零或正数,没有负数。
  2. 溢出行为:当无符号数的值超出其表示范围时,它会绕回到零。例如,假设unsigned int的最大值为4294967295,如果再加1,就会变成0。
    unsigned int max = 4294967295;
    max += 1; // 结果是0
    

有符号数与无符号数运算中的常见问题

  1. 混合运算:在有符号数和无符号数混合运算时,结果可能不符合预期。

    unsigned u = 10;
    int i = -3;
    std::cout << u + i << std::endl; // i被转换为无符号数,导致结果出乎意料
    
  2. 循环控制:在控制循环的条件中,如果使用无符号数作为循环变量,要特别小心,因为它永远不会小于0。

    for (unsigned u = 10; u >= 0; --u) {std::cout << u << std::endl; // 无限循环
    }
    

C++标准中的相关定义

  1. 整数提升:当执行二元运算时,C++标准要求对操作数进行整数提升。例如,有符号charshort等会被提升为int,无符号的会被提升为unsigned int

    char c = 'a';
    int result = c + 1; // 'a'被提升为int,然后再进行加法运算
    
  2. 算术转换:在进行二元运算时,如果两个操作数类型不同,C++会进行算术转换,将较低等级的类型转换为较高等级的类型。

    unsigned u = 42;
    int i = -42;
    std::cout << i + u << std::endl; // i被转换为无符号数
    

安全使用建议

  1. 尽量避免混合使用:尽量避免将有符号数和无符号数混合使用,以减少潜在的错误。
  2. 检查范围:在进行转换或运算前,检查数值是否在目标类型的表示范围内。
  3. 使用静态分析工具:使用静态分析工具检查代码中的潜在问题,例如混合运算带来的隐患。

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

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

相关文章

DevExpress学习系列文章

一&#xff1a;DevExpress Installed 二&#xff1a;Application UI 三&#xff1a;Data Management Controls 四&#xff1a;Skins 系列文章相关代码&#xff1a;DevExpressDemo: DevExpress学习过程中的Demo

react项目--博客管理

文章目录 技术栈登录存信息配置tokenhooks使用路由配置各页面技术总结首页发布文章文章详情页 个人主页分类页 本篇文章总结一个开发的react项目—博客系统 技术栈 React、react-redux、react-router 6&#xff0c;Ant Design&#xff0c;es6&#xff0c;sass&#xff0c;webp…

RPA-UiBot6.0数据整理机器人—杂乱数据秒变报表

前言 友友们是否常常因为杂乱的数据而烦恼?数据分类、排序、筛选这些繁琐的任务是否占据了友友们的大部分时间?这篇博客将为友友们带来一个新的解决方案,让我们共同学习如何运用RPA数据整理机器人,实现杂乱数据的快速整理,为你的工作减负增效! 在这里,友友们将了…

成功解决No module named ‘sklearn’(ModuleNotFoundError)

成功解决No module named ‘sklearn’(ModuleNotFoundError) &#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&#xff01;&#x1f387; &#x1f…

AI 边缘计算平台 - 回归开源 BeagleY-AI 简介

BeagleBoard.org 于 3 月 27 号发布了一款单板计算机 BeagleY-AI &#xff0c;这款 SBC 凭借其完全开源的特性&#xff0c;旨在激发并推动开源社区的生态系统繁荣发展。 一、简介&#xff1a; BeagleY-AI 采用德州仪器新推出的 AM67A AI 视觉处理器。这款处理器集成了四个 64…

开源模型应用落地-LangChain高阶-LCEL-表达式语言(五)

一、前言 尽管现在的大语言模型已经非常强大,可以解决许多问题,但在处理复杂情况时,仍然需要进行多个步骤或整合不同的流程才能达到最终的目标。然而,现在可以利用langchain来使得模型的应用变得更加直接和简单。 LCEL是什么? LCEL是一种非常灵活和强大的语言,可以帮助您更…

UE5基础1-下载安装

目录 一.下载 二.安装 三.安装引擎 四.其他 简介: UE5&#xff08;Unreal Engine 5&#xff09;是一款功能极其强大的游戏引擎。 它具有以下显著特点&#xff1a; 先进的图形技术&#xff1a;能够呈现出令人惊叹的逼真视觉效果&#xff0c;包括高逼真的光影、材…

Redis原理篇——哨兵机制

Redis原理篇——哨兵机制 1.Redis哨兵2.哨兵工作原理2.1.哨兵作用2.2.状态监控2.3.选举leader2.4.failover 1.Redis哨兵 主从结构中master节点的作用非常重要&#xff0c;一旦故障就会导致集群不可用。那么有什么办法能保证主从集群的高可用性呢&#xff1f; 2.哨兵工作原理 …

备战 清华大学 上机编程考试-冲刺前50%,倒数第4天

T1:四操作 有一个n个元素的数列,元素的值只能是0 1 2三个数中的一个&#xff0c;定义四种操作&#xff0c;(1 i x)表示为把第i位替换成x&#xff0c;x也只能是0 1 2三个数中的一个&#xff0c;(2 i j)表示把第i个数到第j个数所有的元素值加1&#xff0c;并对3取模&#xff0c;…

【JS重点06】作用域(面试重点)

目录 一:局部作用域 1 函数作用域 2 块作用域 二:全局作用域 三:作用域链 变量查找机制: 本文章目标:了解作用域对程序执行的影响及作用域链的查找机制 作用域:规定了变量能够被访问的”范围“,离开这个”范围“变量便不能被访问 一:局部作用域 局部作用域分为…

CDR2024软件破解Keygen激活工具2024最新版

CorelDRAW Graphics Suite2024最新版&#xff0c;这是一款让我爱不释手的图形设计神器&#xff01;作为一个软件评测专家&#xff0c;我一直在寻找一款能够提升我的设计效率和创造力的工具。而这款软件&#xff0c;简直就是为我量身定制的&#xff01;&#x1f389; 「CorelDR…

C#进阶高级语法之LINQ

&#x1f433;简介 LINQ是C#编程语言中的一项强大功能&#xff0c;它通过将查询直接集成到编程语言中&#xff0c;大幅度简化了数据查询的代码编写工作。 LINQ的应用场景&#xff1a; 数据源支持&#xff1a;LINQ可查询的数据源类型极为广泛&#xff0c;包括SQL Server数据库…

插卡式仪器模块:示波器模块(插卡式)

• 12 位分辨率 • 125 MSPS 采样率 • 支持单通道/双通道模块选择 • 可实现信号分析 • 上电时序测量 • 抓取并分析波形的周期、幅值、异常信号等指标 • 电源纹波与噪声分析 • 信号模板比对 • 无线充电&#xff08;信号解调&#xff09; 通道12输入阻抗Hi-Z, 1 MΩ…

检索增强生成RAG需要用到的10个资源、工具和Python库

●10个资源和工具 在机器学习和自然语言处理领域&#xff0c;有多种工具和框架可用于实现和使用检索增强型生成&#xff08;RAG&#xff09;模型。以下是一些关键的资源和工具&#xff1a; Hugging Face Transformers&#xff1a; Hugging Face在其广泛使用的Transformers库…

CountDownLatch闭锁

Java并发库提供了CountDownLatch类来实现这个功能。 CountDownLatch类是一个同步工具类&#xff0c;在完成某些运算时&#xff0c;只有其他所有的运算全部完成&#xff0c;当前运算才继续执行。 下面是一个案例来说明CountDownLatch&#xff1a; 说明&#xff1a;当前有 5 个…

matlab使用教程(95)—显示地理数据

下面的示例说明了多种表示地球地貌的方法。此示例中的数据取自美国商务部海洋及大气管理局 (NOAA) 国家地理数据中心&#xff0c;数据通告编号为 88-MGG-02。 1.关于地貌数据 数据文件 topo.mat 包含地貌数据。topo 是海拔数据&#xff0c;topomap1 是海拔的颜色图。 load t…

java-ArrayList的底层原理

Java中的ArrayList是基于数组实现的动态数组&#xff0c;它提供了比标准数组更多的灵活性&#xff0c;特别是在大小方面。ArrayList的底层原理主要依赖于以下几个关键点&#xff1a; 1. 数组&#xff1a;ArrayList内部维护了一个数组&#xff0c;这个数组用于存储集合中的元素。…

nodejs 中 axios 设置 burp 抓取 http 与 https

在使用 axios 库的时候&#xff0c;希望用 burp 抓包查看发包内容。但关于 axios 设置代理问题&#xff0c;网上提到的一些方法不是好用&#xff0c;摸索了一段时间后总结出设置 burp 代理抓包的方法。 nodejs 中 axios 设置 burp 抓包 根据请求的站点&#xff0c;分为 http …

web前端:作业二

<!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>/* 1.将ul的子l…

Java加密体系结构参考指南-Java Cryptography Architecture

本文是从英文的官网摘了翻译的&#xff0c;用作自己的整理和记录。水平有限&#xff0c;欢迎指正。版本是&#xff1a;22 原文地址&#xff1a;https://docs.oracle.com/en/java/javase/22/security/java-cryptography-architecture-jca-reference-guide.html#GUID-815542FE-CF…