use*_*570 3 c++ signed integer-overflow undefined-behavior c++11
我试图理解这句话的含义:
(int)(unsigned)-1 == -1;
Run Code Online (Sandbox Code Playgroud)
据我目前的理解,会发生以下事情:
-1是一个有符号的 int并且被转换为无符号的 int。其结果是,由于环绕行为,我们获得了该类型可以表示的最大值unsigned。
接下来,unsigned我们在步骤 1 中获得的这种类型最大值现在被转换为signed int。但请注意,该最大值是一个unsigned type。所以这超出了的范围signed type。并且由于有符号整数溢出是未定义的行为,因此程序将导致未定义的行为。
我的问题是:
PS:我知道如果它是未定义的行为(而不是定义的实现),那么我们不能依赖程序的输出。所以我们不能说我们是否总是会得到true或false。
总而言之unsigned int,这部分是合法的。
从 C++20 开始,超出范围的转换为int合法的,并且之前是实现定义的(但无论如何在实践中工作正常)。这里没有UB。
这两个强制转换相互抵消(同样,在 C++20 中保证,之前是实现定义的,但无论如何在实践中都是有效的)。
有符号溢出通常是 UB,是的,但这仅适用于由计算引起的溢出。转换引起的溢出是不同的。
如果目标类型有符号,并且源整数可以用目标类型表示,则该值不会更改。否则结果是:
(C++20 之前)实现定义
(C++20 起) 目标类型的唯一值等于源值模,其中是用于表示目标类型的位数。
2nn(请注意,这与有符号整数算术溢出不同,后者是未定义的)。
有关转换如何运作的更多细节。
假设int占用unsigned intN 位。
int两者都可以表示并且unsigned int不会因转换而改变的值。所有其他值均增加或减少 2 N以适应该范围。
这很方便,不会改变值的二进制表示形式。
例如int -1对应(最大值),两者都用二进制表示。同样,(最小值)对应于(最大值+1)。unsigned int 2N-1unsigned int11...11int -2N-1intunsigned int 2N-1int
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]
Run Code Online (Sandbox Code Playgroud)