【发布时间】:2020-02-24 01:27:45
【问题描述】:
uint32_t a = -1; // 11111111111111111111111111111111
int64_t b = (int64_t) a; // 0000000000000000000000000000000011111111111111111111111111111111
int32_t c = -1; // 11111111111111111111111111111111
int64_t d = (int64_t) c; // 1111111111111111111111111111111111111111111111111111111111111111
从上面的观察来看,似乎只有原始值的sign 很重要。
即,如果原始 32 位数字是无符号的,则将其转换为 64 位值将在其左侧添加 0's,无论目标值是有符号还是无符号,并且;
如果原始 32 位数字是有符号的且为负数,则将其转换为 64 位值将在其左侧添加 1's,无论目标值是有符号还是无符号。
以上说法正确吗?
【问题讨论】:
-
对于您展示的具体示例,您所看到的只是值没有变化。在第一种情况下,4294967295 保持 4294967295,在第二种情况下 -1 保持 -1。
-
是的,我不是在谈论值本身,而是在谈论它的符号扩展。
-
由于值没有改变,它不是关于 C 的属性,而是关于无符号和 2 的补码表示的属性。对于无符号值,是的,前面会添加零。对于有符号值,是的,将发生符号扩展。当表示很重要时,固定宽度的整数非常方便。 究竟是什么意思?
-
不,事实并非如此。对于给出的特定示例,从固定宽度的 32 位整数到
int64_t事情的行为就像您描述的那样。一旦您离开固定宽度类型的领域,签名表示就是实现定义的。此外,类型的宽度也很重要。您必须参考Usual arithmetic conversions 以了解这些值会发生什么。从那里,了解表示可以让您确定二进制结果。 -
@paxdiablo 从签名到未签名,我认为您所说的是正确的。问题是 Jeff 对二进制表示的许多陈述并不总是正确的。
标签: c sign-extension