IS(Int)(无符号)-1==未定义的行为
我在试着理解这句话的意思:
(int)(unsigned)-1 == -1;
根据我目前的理解,会发生以下情况:
-1
是签名int
,并强制转换为无签名int
。这样做的结果是,由于回绕行为,我们获得了可以由unsigned
类型表示的最大值。
接下来,我们在步骤1中获得的
unsigned
类型的最大值现在强制转换为signed int
。但请注意,此最大值是unsigned type
。因此,这超出了signed type
的范围。由于有符号整数溢出是未定义的行为,因此程序将导致未定义的行为。
我的问题是:
- 我上面的解释正确吗?如果没有,则实际发生了什么。
- 这是我怀疑的未定义行为还是实现定义的行为。
true
还是false
。
解决方案
强制转换为unsigned int
换行,此部分是合法的。
超出范围强制转换为int
从C++20开始是合法的,并且以前是实现定义的(但无论如何在实践中都是正确工作的)。这里没有UB。
这两个强制转换相互抵消(同样,在C++20中得到保证,以前定义了实现,但在实践中仍然可以工作)。
带符号溢出通常是UB,是的,但这只适用于由计算引起的溢出。转换导致的溢出不同。cppreference
如果目标类型是有符号的,则如果源整数可以用目标类型表示,则该值不会更改。否则结果为:
(直到C++20)实现定义
(从C++20开始)目标类型的唯一值等于源值的模
2n
,其中n
是用于表示目标类型的位数。(请注意,这与未定义的带符号整数算术溢出不同)。
有关转换如何工作的更多详细信息。
假设int
和unsigned int
占用N位。
int
和unsigned int
均可表示的值在转换过程中保持不变。所有其他值都将增加或减少2N以适合该范围。
这很方便,不会更改值的二进制表示形式。
例如int
-1
对应于unsigned int
2N-1
(最大的unsigned int
值),两者都用二进制表示为11...11
。同样,int
-2N-1
(最小int
值)对应于unsigned int
2N-1
(最大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]
相关文章