【问题标题】:Difference and nuances of std::uint8_t(-1) vs std::uint8_t(0xffu)std::uint8_t(-1) 与 std::uint8_t(0xffu) 的差异和细微差别
【发布时间】:2021-04-15 16:42:33
【问题描述】:

我在这里看到了 std::uint8_t(-1) 的用法:

https://en.cppreference.com/w/cpp/language/fold

CPP 参考说明了字节顺序交换,我想知道与 std::uint8_t(0xffu) 相比有什么区别?

在 x86 上似乎没有任何区别: https://godbolt.org/z/Kb7v8K1nT

我的问题可能是阅读过多,这只是某人编写代码的惯例,并没有更深层次的含义。但是,我怀疑这是由于代码在某些深奥的架构上的可移植性,其中 CHAR_BIT != 8

但后来我想知道在需要 8 位对齐的字节顺序交换的情况下,我希望 std::uint8_t(0xffu) 并强制进行 8 位计算即使 CHAR_BIT != 8 那么这会产生更多的可移植代码,因为它预计不会在平台之间改变?例如,当我生成 TCP/IP 数据包并且需要具有特定的字节顺序(并且可能交换一些值)时,无论使用什么底层架构,它们都需要相同的值。

也许在一个半字节的字符交换中(我们期望类型的大小会改变和机制会调整)然后 std::uint8_t(-1) 会更好?

本质上,使用 std::uint8_t(-1) 我们是说无论有多少位都将所有位设置为高(如果 CHAR_BIT > 8 则更多),而使用 std ::uint8_t(0xffu) 我们想要 8 位设置(如果 CHAR_BIT

或者有什么我完全想念的吗?

【问题讨论】:

  • 这取决于您所谈论的 C++ 标准。
  • 感谢@Nicol Bolas,我更喜欢使用 C++17,有时也使用 C++20。我错过了一些细微差别吗?
  • 虽然使用 std::uint8_t(0xffu) 我们想要 8 位设置(如果 CHAR_BIT uint8_t 不会存在,除非实现也提供 8 位类型。
  • 另一种选择是std::uint8_t(~0u),它避免了 1 的补码 vs 2 的补码表示 -1。 C++ 现在要求 C++ 抽象机的行为就像 2 的补码一样,因此它可能不如过去重要(假设您的目标是 1 的补码机器)。
  • CHAR_BIT < 8 在 C 或 C++ 实现中是不允许的。

标签: c++


【解决方案1】:

这是获取无符号类型最大值的捷径,无需关心它的宽度。所有无符号类型都以模 2n 运行,因此 unsigned_type(-1)std::numeric_limits<unsigned_type>::max() 相同。

【讨论】:

  • 所以我在考虑改变 uint8_t 的位宽,而更多的是在 uint16_t 与 uint8_t 等类型之间轻松更改,而无需解决重写字面数字?
  • 是的,它有助于这样的重构。您不必更新幻数。虽然您可以将-1 视为一个神奇的数字,但表达式unsgined_type(-1) 是一个定义明确的常量,至少其定义取决于unsigned_type 究竟是什么。例如,unsigned long{-1} 将始终为您提供最大值(所有位设置),而 unsigned long{0xffffffffu} 可能正确也可能不正确,具体取决于 unsigned long 的实现(Windows 4 字节,*Nix 8 字节)
  • @MooingDuck C++ 一直要求 声明为无符号的无符号整数应遵守算术模 2n 的规律,其中 n 是该特定整数大小的值表示中的位数 这意味着-1 总是成为最大值。
  • 在 'unsigned long{0xffffffffu}' 的切线上会使用更大的数字,并且 'lu' 或 'llu' 比 'u' 更安全,并且让字面量在最坏的情况下被强制转换/截断-案例场景。但现在我认为 -1 是最安全的
  • @AntonKrug 我个人会使用std::numeric_limits<unsigned_type>::max() 而不必担心。我喜欢我的代码富有表现力,unsigned_type(-1) 有效,我发现std::numeric_limits<unsigned_type>::max() 更能自我记录。
猜你喜欢
  • 1970-01-01
  • 2020-12-09
  • 2017-11-24
  • 2015-10-06
  • 1970-01-01
  • 1970-01-01
  • 2011-11-21
  • 1970-01-01
相关资源
最近更新 更多