将带符号数转换为无符号数

7

这样做正确吗?

typedef unsigned int Index;

enum
{
  InvalidIndex = (Index) -1 
};

我读过跨平台不安全的说法,但我在许多“专业”的代码中看到了这种用法...


2
我希望你能停止在每个问题的开头写“嗨”... - Lightness Races in Orbit
4个回答

6
你所读的可能是出于恐惧、不确定性和怀疑。你所读内容的作者可能认为 (unsigned)-1 会发生下溢并在某些系统上潜在地引起混乱,因为位表示法不能给你 UINT_MAX 作为补偿。
然而,作者是错误的,因为标准保证无符号值在达到其范围的边缘时会环绕。无论涉及哪些位表示,(unsigned)-1 就是 std::numeric_limits<unsigned>::max()。没有例外。
我不确定这里的好处是什么。你将得到那个大的最大值...如果这样可以接受,我想你就可以继续了。

1
你可能不知道enum的底层类型,但你知道它能够保存任何枚举常量的值,否则就会在编译时出错。UINT_MAX是一个值,这是枚举常量唯一合法的取值。 - James Kanze

4
如果你想要获取UINT_MAX,我相信这是实现的最佳方式。将-1强制转换为“unsigned”将保证产生UINT_MAX。这在注释中有解释。

3
UINT_MAX是一个无符号整数类型的最大值。它的保证并不是因为位表示中的有符号性质,而是因为将值转换为无符号类型会执行模算术。正好在二进制补码表示法中,这会使得位模式保持不变,但在一的补码和符号-大小表示法中,位模式会发生改变,并且强制转换确保进行这种操作。 - Steve Jessop
你的意思是 INT_MAX,但这里实际上与之相关的是 UINT_MAX。不是因为位数的原因,而是因为标准规定无符号值会回绕。然后当你再次将其转换为 signed 用于枚举(如果底层类型是有符号的话),你会得到 -1。 - Lightness Races in Orbit
@Tomalak: "你会得到-1的返回值" - 在实践中是这样,但原则上不是这样的(4.7/3)。 - Steve Jessop
1
@Tomalak:我并不是在宣称我喜欢这个规则,只是在回答 Stack Overflow 上的问题时喜欢指出它! - Steve Jessop
1
@SteveJessop:我并不是在说我不同意这种行为;只是C++必须得找点事来让我头疼 :P - Lightness Races in Orbit

2

这段代码是不安全的,因为enum(枚举类型)的定义不够明确。

有关此问题的更多信息,请参见C++中的枚举类型是有符号还是无符号?

总之,你写的代码最终会被转换为(int)(unsigned int)(int),我不确定你想要实现什么功能。


这是完全安全的,因为表达式的值是完全定义的,且该值可以表示在枚举中,否则就是一个错误。 - James Kanze

-2

不太确定这是否是实现定义,但将-1(显然为有符号数)强制转换为无符号整数会导致下溢,通常会导致极大的值(即INT_MAX)。


4
编写此类代码时通常的意图是这样的。 - Dan F
1
这并不是下溢,因为无符号值被定义为环绕。 - Lightness Races in Orbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接