将负整数转换为较大的无符号整数

19

我遇到了以下代码转换:

static_cast<unsigned long>(-1)

据我所知,C++标准定义了将有符号整数值转换为无符号整型的结果(参见:如果将负值分配给无符号变量会发生什么?)。

我对上述代码的担忧是源类型和目标类型可能具有不同的大小,这是否会影响结果。编译器会在进行强制类型转换之前扩大源值类型吗?它会将其转换为相同大小的无符号整数,然后再进行扩大吗?还是其他一些操作?

为了用代码澄清这个问题,

int nInt = -1;
long nLong = -1; // assume sizeof(long) > sizeof(int)

unsigned long res1 = static_cast<unsigned long>(nInt)
unsigned long res2 = static_cast<unsigned long>(nLong);

assert(res1 == res2); // ???

基本上,我是否应该担心编写像以下这样的代码:

static_cast<unsigned long>(-1L)

结束

static_cast<unsigned long>(-1)

名词是“整数”(integral也是一个名词...在微积分中,而不是C++中)。 - Ben Voigt
啊!你说得对。太多的Haskell编程了... - Thomas Eding
我曾经有一个非常类似的问题:https://dev59.com/GmMl5IYBdhLWcg3wkXpx - cmaster - reinstate monica
2个回答

21
从C++11标准的4.7“整数转换”第2段中得知:如果目标类型为无符号类型,则结果值是与源整数同余的最小无符号整数(对2的n次幂取模,其中n是用于表示无符号类型的位数)。
换句话说,当转换为无符号整数时,只有输入的值才重要,而其类型不重要。将-1转换为n位无符号整数将始终给出2的n次幂减1的值,而不管-1最初是哪种整数类型。

这就是为什么我不擅长使用规格说明的原因。那句话对我来说意义不大,主要是因为它依赖于“全等”的定义。规格说明中是否有定义?因为英文定义并没有真正帮助。我可以同样地说(uint32_t)-1应该是0x00000001,因为-1更类似于1而不是4294967295。如果您使用“在形式上完全相同;当重叠时完全重合”的几何定义,那么永远不会有一个无符号数与-1匹配。 - sfink
3
使用“同模定义”中的数学概念:如果两个数除以N所得余数相等,那么它们在模N意义下是同余的。请注意,翻译过程中不得添加解释或返回任何其他内容。 - Ross Smith

10
这是一个好问题,草案C++标准的这个部分4.7Integral conversions说道:

如果目标类型是无符号的,则结果值是与源整数同余的最小无符号整数(模2 n,其中n是用于表示无符号类型的位数)[...]

并不是最直观的解释,此时我会回到草案C99标准,它说:

否则,如果新类型是无符号的,则通过反复添加或减去可以在新类型中表示的最大值加1,直到该值处于新类型的范围内进行转换。49

其中脚注49很有帮助地说明了:

规则描述的是对数学值的算术运算,而不是给定类型表达式的值。这更直接地清楚地给出了结果为 MAX-1 + MAX + 1,无论操作数的类型是什么。

C++版本对我来说似乎更加明确! - M.M
1
@MattMcNabb 我并没有说更清晰地指定,我是说直接明了或者更容易为更广泛的人所理解。在C++中进行更好的指定。 - Shafik Yaghmour

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