c++ - 是 (int)(unsigned)-1 == -1 未定义的行为

标签 c++ c++11 undefined-behavior integer-overflow signed

我正在尝试理解语句的含义:

(int)(unsigned)-1 == -1;

据我目前的理解,会发生以下事情:

  1. -1 是一个 signed int 并被强制转换为 unsigned int。这样做的结果是,由于环绕行为,我们得到了 unsigned 类型可以表示的最大值。

  2. 接下来,我们在步骤 1 中得到的这个 unsigned 类型最大值现在被转换为 signed int。但请注意,这个最大值是一个无符号类型。所以这是签名类型超出范围。而且由于有符号整数溢出是未定义的行为,程序会导致未定义的行为

我的问题是:

  1. 我上面的解释正确吗?如果不是,那么实际发生了什么。
  2. 这是我怀疑的未定义行为还是实现定义的行为。

PS:我知道如果它是未定义的行为(与定义的实现相反),那么我们不能依赖程序的输出。所以我们不能说我们是否总是会得到 truefalse

最佳答案

转换为 unsigned int绕一圈,这部分是合法的。

超出范围强制转换为 int从 C++20 开始是合法的,并且之前是实现定义的(但无论如何在实践中都能正常工作)。这里没有UB。

这两个转换相互抵消(同样,在 C++20 中得到保证,之前由实现定义,但在实践中仍然有效)。

有符号溢出通常是 UB,是的,但这仅适用于由计算引起的溢出。转换造成的溢出是不同的。

cppreference

If the destination type is signed, the value does not change if the source integer can be represented in the destination type. Otherwise the result is:

(until C++20) implementation-defined

(since C++20) the unique value of the destination type equal to the source value modulo 2<sup>n</sup> where n is the number of bits used to represent the destination type.

(Note that this is different from signed integer arithmetic overflow, which is undefined).


关于转换如何工作的更多细节。

假设 intunsigned int占用N位。

int 都可以表示的值和 unsigned int转换不会改变。所有其他值增加或减少 2N 以适应范围。

这不会改变值的二进制表示。

例如int -1对应于 unsigned int 2<sup>N</sup>-1 (最大 unsigned int 值),两者都表示为 11...11在二进制。同样,int -2<sup>N-1</sup> (最小 int 值)对应于 unsigned int 2<sup>N-1</sup> (最大 int 值 + 1)。

int:   [-2^(n-1)] ... [-1] [0] [1] ... [2^(n-1)-1]
            |           |   |   |           |
            |           '---|---|-----------|-----------------------.
            |               |   |           |                       |
            '---------------|---|-----------|----------.            |
                            |   |           |          |            |
                            V   V           V          V            V
unsigned int:              [0] [1] ... [2^(n-1)-1] [2^(n-1)] ... [2^n-1]

关于c++ - 是 (int)(unsigned)-1 == -1 未定义的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70797019/

相关文章:

C++代码在for循环的条件下给出运行时错误而如果它被具有相同意义的代码替换则编译正确

c++ - Win32 : Bring a window to top

c++ - 我无法通过 C++ 中的函数式编程重现函数内存

c++ - 在 C++ 中,如何在维护指向对象的指针的同时将对象推送到 vector ?

c++ - std::is_empty<T> 如何在 VS2015(或任何编译器)中实现?

c++ - 带有 typeid 调用的 UB

c++ - std::forward 和复制构造函数

c++ - std::set 迭代器的返回类型冲突

c++ - 通过具有可变参数列表的函数计算欧氏距离

c++ - unique_ptr : linked list entry deletion