RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1587043
Accepted
Yulia
Yulia
Asked:2024-07-13 17:29:46 +0000 UTC2024-07-13 17:29:46 +0000 UTC 2024-07-13 17:29:46 +0000 UTC

2^32 模加法的实现和溢出问题?

  • 772

需要实现模2^32的加法。

首先想到的是简单地添加两个数字(uint32_t)的想法;之后就会溢出,但结果是4个低字节,应该是模2^32的加法结果。

但这不会一不小心就变成“未定义行为”吗?如果是这样,如何以不同的方式实现这种添加?

c++
  • 3 3 个回答
  • 90 Views

3 个回答

  • Voted
  1. Best Answer
    VladD
    2024-07-13T20:36:54Z2024-07-13T20:36:54Z

    根据文档,对所有无符号类型执行的计算均以 2ⁿ 为模执行,其中n是位数,并且不会导致未定义的行为(当然除以零除外)。

    因此,您所要做的就是uint32_t按照您的预期使用类型。

    但是使用有符号类型(例如,int32_t)更加危险,因为在这种情况下溢出是未定义的行为。

    不要忘记将文字(如 1)强制转换为 type uint32_t,否则编译器可能会推断结果表达式不是您想要的类型(例如,有符号的)。

    但是,某些编译器具有强制有符号类型遵守与无符号类型相同的规则的编译开关。例如,gcc 有一个选项-fwrapv.但这将使您的代码不再可移植。


    添加:评论中的讨论使我确信,uint32_t在特殊情况下使用 taki 可能会导致未定义的行为。要检查您的情况是否非异常,请插入以下断言:

    #include <cstdint>
    #include <type_traits>
    
    static_assert(std::is_unsigned_v<decltype(+(uint32_t)0)>);
    

    对于所有“正常”系统,此断言通过。

    如果你的系统很奇特怎么办?

    • 对于 MSVC 来说,该系统并不陌生。
    • 对于 GCC/Clang,使用 key -fwrapv,它会阻止 UB。
    • 如果系统上的大小int大于 32 位,请读取 中的所有内容unsigned int,并在最后(一次)剪掉不必要的位。
    • 如果您的系统上的大小long是 32 位,则以 unsigned long 计数(但您的系统必须是非奇异的)
    • 如果大小int小于32位且大小long较大,则读入unsigned long,在最后(一次)截掉不需要的位。

    了解有哪些奇异病例以及它们来自何处。事实上,在加法之前,C++ 将尺寸较小的数字类型减少int为类型intor unsigned int,并将字符类型(例如char32_t)减少为类型int, unsigned int, long int, unsigned long int, long long intor unsigned long long int。

    在正常系统中,它是或uint32_t的别名,不会出现任何问题。但该标准并不禁止做一些愚蠢的事情,例如在 上定义别名,该别名有权被带到或 那里。unsigned intunsigned long intuint32_tchar32_tintlong int

    (整个幻象的确切规则在标准第 7.3.7 章中有描述。)

    是的,在一个奇异的系统上可能没有类型uint32_t。

    建议的断言只是检查整型提升 ( ) 后类型uint32_t( ) 的值至少仍然是无符号类型 ( )。(uint32_t)0+(uint32_t)0std::is_unsigned_v<decltype(...)>

    • 2
  2. Stanislav Volodarskiy
    2024-07-13T20:16:30Z2024-07-13T20:16:30Z

    static_cast<uint32_t>(static_cast<uint64_t>(a) + static_cast<uint64_t>(b))uint32_t将执行模2 32类型的两个操作数的加法,没有未定义的行为。编译器有足够的信息来在所有流行的处理器上执行添加到单个汇编指令中 - 强制转换不会在代码中插入额外的指令。

    • 1
  3. Кирилл Ланской
    2024-07-13T18:36:40Z2024-07-13T18:36:40Z

    它不会,因为额外的位根本不会保留在内存中,并且对于无符号我们将得到零。未定义的行为是指离开链接、指针、迭代器、向量重定位等的可见区域。

    • -1

相关问题

  • 编译器和模板处理

  • 指针。找到最小数量

  • C++,关于枚举类对象初始化的问题

  • 函数中的二维数组

  • 无法使用默认构造函数创建类对象

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5