将Short Int转换为Unsigned Short的C语言方法

4
在 C 语言中,短整型(short int)包含16个位(bit),其中第一个位(bit)表示数值是正数或负数。我有一个以下的 C 程序:
int main() {
    short int v;
    unsigned short int uv;
    v = -20000;
    uv = v;
    printf("\nuv = %hu\n", uv);
    return 0;
}

因为变量v的值是负数,所以我知道变量的第一位是1。因此,我期望程序的输出结果等于uv=52,768,因为20,000 + (2^15) = 52,768

但实际上,输出结果却是uv=45,536。我的逻辑哪里出了问题?


2
数字以二进制补码形式存储(https://en.wikipedia.org/wiki/Two%27s_complement)。因此,最大的无符号数(0xFFFF)实际上是-1。 - twain249
2
负数不是通过简单地设置最后一个位来表示的。它们是作为二进制补码表示的,即所有位都取反再加一。请参见https://dev59.com/6XNA5IYBdhLWcg3wNq8y。 - Marian
@Marian 这篇文章非常有用。谢谢! - RyeGuy
1个回答

7
您看到的行为可以通过 C 的转换规则来解释:
6.3.1.3 有符号和无符号整数
1 当将具有整数类型的值转换为除 _Bool 以外的另一种整数类型时,如果该值可以由新类型表示,则它不会发生变化。
2 否则,如果新类型是无符号的,则通过重复添加或减去一个比新类型中可以表示的最大值大一的值,直到该值在新类型的范围内为止进行转换。
(此引用来自 C99。)
-20000 不能由 unsigned short 表示,因为它是负数。目标类型是无符号的,因此通过反复添加 65536(即 USHORT_MAX + 1)进行转换,直到它处于范围内:-20000 + 65536 正好是 45536。
请注意,这种行为是由C标准规定的,与负数在内存中实际表示方式无关(特别是,在使用补码反码的机器上,它的工作方式也是相同的)。

1
模数行为是由标准规定的 - USHORT_MAX65536 不是(它可能更大) - M.M

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