在C语言中,将有符号整数转换为无符号整数是否会改变位值?

6
我已经进行了一些快速测试,发现在C语言中将signed int转换为unsigned int不会改变位值(通过在线调试器验证)。
我想知道的是这个行为是由C标准保证的还是仅仅是普遍但不百分之百确定的行为?

2
它改变了上下文,也就是值的含义。所有计算机数据都由一组有意义的数字组成,这些数字在上下文中具有特定的含义。但是当将int转换为float时,表示法会发生变化,这时情况就有所不同了。 - Weather Vane
1
@LegendofPedro 如果你想要两个已知为非负数的 int 值的和,而不用担心 int 溢出的风险,那么这是安全的。 - Weather Vane
2
@WeatherVane(和LegendofPedro):无论有符号整数的符号如何,转换后的结果都已经完美定义,不会发生溢出的危险。 - Steve Summit
@SteveSummit,我需要将一个有符号整数变量复制到一个无符号整数数组的元素中(用于串口传输的缓冲区)。由该缓冲区携带的数据可以具有不同的类型,并由目标解释。我知道这听起来非常明显,而且我已经做过这种事情数百次,但当我开始思考最佳方法时,结果并不那么明显 :) - Guillaume Petitjean
@GuillaumePetitjean 在数据传输中将数据视为无符号数是我在回答Weather Vane时提到的“捷径”之一。个人认为这是一种很好的技巧,尽管我想有一个问题,即在另一端,那个无符号整数是否保证可以转换回原始的有符号整数,特别是如果它是负数。 - Steve Summit
显示剩余6条评论
2个回答

7
signed int转换为unsigned int在使用二进制补码实现的C语言编译器(这是最常见的情况)时,不会改变位表示,但会改变负数的位表示,包括可能的负零,在反码原码系统中都是如此。
这是因为强制类型转换(unsigned int) a未定义为保留位,但结果是将a除以UINT_MAX + 1正余数(或类似于C标准(C11 6.3.1.3p2)所述):

该值由重复加或减新类型中可以表示的最大值加一的值,直到该值位于新类型的范围内。

对于负数的二进制补码表示法是用于带符号数的最常用表示法正是因为它具有负值n映射为数学值n + UINT_MAX + 1的相同位模式的性质——这使得可以使用相同的机器指令进行带符号和无符号加法,而负数将因环绕而起作用。

2

将有符号整数强制转换为无符号整数是必要的,以生成正确的算术结果(相同的数字),无符号整数的大小,可以这么说。也就是说,在进行强制转换后,会得到相同的数字,但被无符号整数的大小所限制。

int i = anything;
unsigned int u = (unsigned int)i;

在一个拥有32位整数的计算机上,要求等于模232。如果我们尝试说接收%0x100000000,但事实证明这并不完全正确,因为C规则表明当你将负整数除以正整数时,你会得到向0舍入的商和负余数,这不是我们想要的模数。如果 是0或正数,很容易看出 将具有相同的位模式。如果 是负数,并且你在2's complement机器上,结果也保证具有相同的位模式。绝大多数今天的机器使用2's complement。但如果你在1's complement或sign/magnitude机器上,我相信位模式不总是相同的。所以,底线是,位模式的相同不是由C标准保证的,而是由C标准的要求和2's complement算术的特定组合产生的。

1
你应该用二进制补码的C语言实现来表达规则,而不是二进制补码的机器。虽然C语言通常旨在使用与目标处理器匹配的特性,但实现最终决定权在手。如果我编写了一个C语言实现,使用一的补码来支持我想在计算机博物馆中展示的古老软件,即使底层机器是二进制补码,它也会遵守一的补码规则。 - Eric Postpischil
@EricPostpischil,你是否知道现有的补码机器? - Guillaume Petitjean
正如我刚刚所说,C语言可以通过软件实现而不是硬件。因此,底层机器并不是决定性因素。因此,任何特定类型的机器的存在都是无关紧要的。 C标准中规定的规则很清楚:行为由C实现定义,而不是由硬件定义。 - Eric Postpischil
我完全理解@EricPostpischil的意思。但是我猜在实践中,在2的补码机器上选择1的补码C实现没有意义。只是好奇。 - Guillaume Petitjean
真的,认为“我知道真相,但这个方法对我有效,在熟悉的情况下,使用当前系统,忽略任何未来可能性,使用当前软件,忽略任何未来可能性。因此,我将忽略已知真相,教授错误观点。”这种思维方式是无法理解的。没有人会质疑C标准规定行为由实现而不是机器定义。因此,没有理由声明否认这一点。请传授真相。 - Eric Postpischil
显示剩余8条评论

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