为什么unsigned int包含负数

8

我知道无符号数字(unsigned short,int和long)仅包含正数,但以下简单程序成功地将负数分配给了一个无符号整数:

  1 /*
  2  * =====================================================================================
  3  *
  4  *       Filename:  prog4.c
  5  *
  6  * =====================================================================================
  7  */
  8 
  9 #include <stdio.h>
 10 
 11 int main(void){
 12 
 13     int v1 =0, v2=0;
 14     unsigned int sum;
 15     
 16     v1 = 10;
 17     v2 = 20;
 18     
 19     sum = v1 - v2;
 20     
 21     printf("The subtraction of %i from %i is %i \n" , v1, v2, sum);
 22     
 23     return 0;
 24 }

输出结果为: 20减去10等于-10

4
您的信息有误导性。应该写成“从10减去20是...”,这是您所计算的内容。 - Greg Hewgill
我不是在寻求这样一个问题的解决方案,我想要理解关于它的思路。 - Muhammad Hewedy
可能是C Unsigned int providing a negative value?的重复问题。 - Baum mit Augen
4个回答

22

%i 是用于打印 有符号 整数的格式说明符;您需要使用 %u 来打印无符号整数。


2
请注意,由于无符号值只能存储非负值,因此从另一个无符号整数中减去一个无符号整数将导致下溢。如果被减数小于减数,则会发生下溢。请参阅:http://www.topbits.com/integer-overflow.html - LandonSchropp

8
使用printf函数,格式符%i输出的是一个带符号的整数(signed int)。使用%u可以输出一个无符号整数(unsigned int)。这是C语言初学者常遇到的问题。回答你的问题,v1 - v2的结果是-10,但是sum是一个无符号整数,所以真正的答案可能是4294967286(2的32次方减去10)。尝试使用The subtraction of %i from %i is %u \n来查看输出结果吧 :)

6

在内存中,有符号整数和无符号整数的大小是相同的,它们之间的唯一区别在于如何解释它们。有符号值使用二进制补码表示。

如果您将0xFFFFFFFF放入4字节的内存位置中,并询问其中的值是多少?如果我们将其解释为有符号整数,则其值为-1,但如果我们将其解释为无符号整数,则值为4294967295。无论哪种方式,它都是相同的位模式,不同之处在于您赋予它的含义。

当您将10-20分配给无符号整数时,您计算出一个值为-10(C不检查溢出或下溢),即0xFFFFFFF6的位模式,这意味着对于有符号整数,它表示-10,对于无符号整数则表示4294967286。如果您然后告诉编译器(通过使用%i)打印有符号整数,则它将该位模式解释为有符号整数并打印-10;如果您告诉编译器(通过使用%u)打印无符号整数,则它将该位模式解释为无符号整数并打印4294967286。


所以,我解释位模式的方式控制着内存中的值。谢谢。 - Muhammad Hewedy
嗯,在内存中的值始终是相同的。它们是相同的位。改变的是输出方式。 - Veky

1

因为在 printf %i 中,存储在 sum 中的无符号整数值被视为有符号十进制整数。


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