如果我递减`std :: size_t(0)`是否等于'std :: size_t(-1)`?

时间:2018-08-01 17:55:38

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

这是证明:

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了,但是我现在真正的问题是,我期望的行为是否定义明确?

2 个答案:

答案 0 :(得分:6)

sfc /scannow 是未指定的无符号整数。

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

当您将有符号整数转换为无符号整数时,对于该无符号类型的常数n,将得到整数模2 n 的值。对于-1,这是2 n -1。

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

这两个值是相同的。

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

  

无符号整数应服从算术模数定律   2 n   哪里   ñ   是值中的位数   该特定整数大小的表示形式。

(引自最新标准草案N3690,但它表示的事实不会在短期内改变;段落编号可能会更改。)

找到有关从有符号整数进行转换的方式的报价会涉及更多的标准追踪;但最终还是您想要的。

答案 1 :(得分:5)

是的,这种行为得到保证。

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

  

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

专门考虑内置的pre-decrement and post-decrement operators

  

[--x表达式与x -= 1完全等效。 ...
  [{]表达式x--修改其操作数的值,就像通过评估x -= 1

因此,减量运算符执行算术运算。