【问题标题】:If I decrement `std::size_t(0)` is that guaranteed to be equal to `std::size_t(-1)`?如果我减少 `std::size_t(0)` 是否保证等于 `std::size_t(-1)`?
【发布时间】:2018-08-01 17:55:37
【问题描述】:

以下是证据:

inline
constexpr std::size_t prev(std::size_t i) {
    --i;
    return i;
}

int main() {
    static const std::size_t i = 0;
    static_assert(prev(i) == std::size_t(-1), "Decrementing should give     std::size_t(-1)");    
    return 0;
}

-std=c++14 编译很愉快。

我遇到这个是因为我有一个循环索引 std::vector 并想向后循环,所以我将其更改为

for (std::size_t i = std::min(idx, v.size() - 1); i != std::size_t(-1); --i) { ... }

现在,我意识到我可以使用 std::vector::reverse_iterator,但我现在真正的问题是,我期望的行为是否明确?

【问题讨论】:

标签: c++ undefined-behavior integer-overflow unsigned-integer


【解决方案1】:

是的

size_t 是一个未指定的无符号整数。

C++ 中的所有无符号整数都被建模为整数环的元素,模 2n 对于特定于该无符号整数类型的某个数字 n。

当您将有符号整数转换为无符号整数时,您会在整数环中为该无符号类型的常量 n 取模 2n 的值。对于 -1,这是 2n-1。

当您将 0 减为无符号整数类型时,您会得到 2n-1。

这两个值是一样的。

参见 C++ 标准中的 [basic.fundamental] 3.9.1/4:

无符号整数应遵循算术模数定律 2n 在哪里 n 是值中的位数 表示特定大小的整数。

(引自最近的标准草案 N3690,但它所代表的真相不会很快改变;段落编号可能会。)

寻找从有符号整数转换如何工作的报价将涉及更多标准追逐;但它最终会成为你想要的。

【讨论】:

    【解决方案2】:

    是的,这种行为是有保证的。

    std::size_t 是无符号整数类型。 Arithmetic on unsigned integers always has well defined semantics:

    无符号整数运算总是模 2n 其中 n 是该特定整数中的位数。

    具体考虑内置pre-decrement and post-decrement operators

    [T]表达式--x 完全等价于x -= 1。 ...
    [T]表达式x-- 修改其操作数的值,就像通过评估x -= 1 一样

    所以减量运算符确实执行算术运算。

    【讨论】:

    • 您会因为增量和减量运算符的详细信息而获得绿色检查。
    猜你喜欢
    • 2018-02-15
    • 1970-01-01
    • 2017-12-23
    • 2014-10-17
    • 2020-05-06
    • 2016-12-05
    • 1970-01-01
    • 2011-10-31
    相关资源
    最近更新 更多