我最近决定实现这一目标并阅读一系列计算机科学书籍,以便更好地为未来做好准备。
目前我正在阅读将有符号转换为无符号小数。我理解大多数人(希望最终变得容易),但是对于以下(32位)的努力:
-2147483647-1U< -2147483647
根据这本书,这评估为真。有一点关于这一点,我仍然在努力,因为我不知道为什么它评估这个。
根据我的理解,我知道在这个计算中它们都被转换为无符号值,因为第一个数字被转换为无符号。因此,减法后第一个数字是-2147483648,然后转换为无符号,或者在减法之前进行无符号转换?
对于冗长的帖子感到抱歉,只是试着理解这一点。
谢谢!
答案 0 :(得分:6)
减法后的第一个数字是-2147483648然后 转换为无符号,或先执行无符号转换 减法?
后者是真的。根据{{3}}:
...否则,如果具有无符号整数类型的操作数具有等级 那么,大于或等于另一个操作数的类型的等级 带有符号整数类型的操作数转换为 具有无符号整数类型的操作数。
因此,所有操作数,用于减法和比较的操作数都转换为无符号。
P.S。为了完整起见,转化程序在C11 Standard "6.3.1.8 Usual arithmetic conversions"中说明:
...如果新类型是无符号的,则转换为 重复加或减一个以上的最大值 可以用新类型表示,直到值在范围内 新类型。
P.P.S。答案是假设int
为32位长。如果小于该值,那么负常数-2147483647
将具有类型long
,其等级高于unsigned int
,即1U
,然后上述将不适用,不会进行转换(感谢@Olaf指出)。
答案 1 :(得分:5)
减法后第一个数字是-2147483648
不完全。首先转换为unsigned
。对于混合int/unsigned
数学,int
将转换为unsigned
。
减去2个unsigned
会产生unsigned
,而unsigned
永远不会消极。
假设32位或更宽unsigned/int
-2147483647-1U
是 int 减去无符号,因此-2147483647
会转换为unsigned 2147483649
,差异为{{1} }}。现在,无符号与unsigned 2147483648
进行比较,因此int
会转换为int
。左边小于右边,结果是真的。
[编辑]
假设窄于32位unsigned 2147483649
,但unsigned/int
使用常见的2&补码编码。经常在2017年的嵌入式8/16位处理器中看到。
long
是长减去较窄的无符号,因此-2147483647-1U
仍为-2147483647
而long
为转换为1U
,差异为int 1
。现在,long -2147483648
与long
进行比较。左边小于右边,结果是真的。
答案 2 :(得分:2)
两者都会提升为未签名且-2147483647-1U == 0x8000000
,(unsigned)-2147483647 == 0x80000001
。
0x8000000 < 0x8000001
是true
与仅签名
相同-2147483647-1 == `-2147483648`
-2147483648 < -2147483647
答案 3 :(得分:1)
这真的很简单。
根据{{3}},如果int
在操作中遇到unsigned int
,则操作数都会转换为unsigned int
。
形式化为6.3.1.8 Usual arithmetic conversions的转换确实描述了自然签名/无符号重新解释如何在repeatedly adding or subtracting one more than maximum value that can be represented in the new type算术中工作(最常见的方式,但不是唯一的方式,表示硬件中的有符号整数)。
对32位有符号数的two's complement算法的工作原理如下:
-2147483647
为2^31+1 == 0b10000000000000000000000000000001
。
现在,由于它涉及1U
(0b00000000000000000000000000000001
)的减法操作,您应该通过重复添加或减去uint32_t
将其转换为UINT32_MAX+1 == 2^32
数字,这会在溢出后生成在相同的二进制表示中(我想这些规则是为了在2的补码(最常见)平台上直接重新解释这些位),从中减去1U
将直接产生
0b10000000000000000000000000000000 == 2^31
,小于2^31+1
。