有符号和无符号int有什么区别


91

有符号和无符号int有什么区别?


5
这是一个真实的问题,答案不是那么简单,而是很微妙的。
R .. GitHub停止帮助ICE,

投票重新开放。它可能是重复的,但这绝对是一个真实的问题。
布莱恩


由于许多语言都使用它们,因此应添加更多标签。
Juan Boero

这个问题可能需要一章来阐述。如果要了解详细信息,请检查“无符号和有符号整数”以获取更多说明。
匿名

Answers:


113

您可能已经知道,ints在内部以二进制存储。通常,aint包含32位,但是在某些环境中可能包含16或64位(甚至是不同的数字,通常但不一定是2的幂)。

但是对于此示例,让我们看一下4位整数。微小,但对说明有用。

由于这样的整数中有4位,因此可以假定16个值之一。16是2到4的幂,或者2乘以2乘以2乘以2。这些值是多少?答案取决于此整数是asigned int还是a unsigned int。使用unsigned int,该值永远不会为负;没有与该值关联的符号。这是四位的16个可能的值unsigned int

bits  value
0000    0
0001    1
0010    2
0011    3
0100    4
0101    5
0110    6
0111    7
1000    8
1001    9
1010   10
1011   11
1100   12
1101   13
1110   14
1111   15

...这是一个四位的16个可能的值signed int

bits  value
0000    0
0001    1
0010    2
0011    3
0100    4
0101    5
0110    6
0111    7
1000   -8
1001   -7
1010   -6
1011   -5
1100   -4
1101   -3
1110   -2
1111   -1

如您所见,对于signed int,最高有效位是1当且仅当数字为负数时。因此,对于signed ints来说,该位称为“符号位”。


11
也许值得指出的是,这是二进制补码格式,如今已经被广泛使用。还有其他表示有符号整数的方法,最引人注目的是补数。
谢德勒2011年

正确。而且,ISO9899 C标准甚至不需要使用一个补码或两个补码。任何其他实际可行的约定都是允许的。
比尔·埃文斯

1
尽管不需要补码,但必须(unsigned)(-1)unsigned(与二进制表示形式无关)的最大可表示值,对于2的补码来说,这是微不足道的,但其他表示形式则不然。
rubenvb

3
@BillEvansatMariposa:该标准说,对于有符号整数,允许使用3种表示形式:符号+大小,2的补码,1的补码。任何其他必须是不可见的程序,被视为这3个之一
阿列克谢伏龙芝

好吧,但在引擎盖下!真正发生了什么!带符号的和带符号的有什么区别!机器如何管理计算?它只是从另一个中减去一个值?它与1111 = 15和1111 = -1有何不同?
Mihail Georgescu

19

intunsigned int是两种不同的整数类型。(int也可以称为signed intsignedunsigned int也可以称为unsigned。)

顾名思义,它int是有符号整数类型,并且unsigned int无符号整数类型。这意味着它int可以表示负值,并且unsigned int只能表示非负值。

C语言对这些类型的范围提出了一些要求。的范围int必须至少为-32767.. +32767,并且该范围的unsigned int必须至少0.. 65535。这意味着两种类型都必须至少为16位。在许多系统上,它们是32位,在某些系统上甚至是64位。int由于大多数现代系统使用二进制补码表示法,因此通常具有额外的负值。

也许最重要的区别是有符号与无符号算术的行为。对于signed int,溢出具有未定义的行为。对于unsigned int,没有溢出;产生值超出类型范围的任何操作都会回绕,例如UINT_MAX + 1U == 0U

任何整数类型(有符号的或无符号的)都会对无限的数学整数集的子范围进行建模。只要您使用类型范围内的值,一切都将起作用。当您接近类型的下限或上限时,会遇到不连续的情况,并且您会得到意想不到的结果。对于有符号整数类型,仅在非常大的负值和正值(超过INT_MIN和)时才会出现问题INT_MAX。对于无符号整数类型,对于非常大的正值和零值会出现问题。这可能是错误的来源。例如,这是一个无限循环:

for (unsigned int i = 10; i >= 0; i --) [
    printf("%u\n", i);
}

因为i始终大于或等于零; 这就是无符号类型的本质。(在循环内,当i为零时,i--将其值设置为UINT_MAX。)


12

有时我们事先知道,存储在给定整数变量中的值将始终为正值(例如,仅用于计数时)。在这种情况下,我们可以声明变量为无符号的,如unsigned int num student;。使用这样的声明,允许的整数值范围(对于32位编译器)将从-2147483648到+2147483647范围从0到4294967295。它可以保留的值。


@Alex 10分钟前,我正在编辑答案的过程中,它是相同的。哈哈
Skuld

12

用外行术语来说,unsigned int是一个不能为负的整数,因此可以假定更大的正值范围。有符号的整数是可以为负的整数,但正整数范围较小,可以换取可以假定的更多负值。


0

实际上,有两个区别:

  1. 打印(例如,cout使用C ++或printfC语言):无符号整数位表示形式由打印函数解释为非负整数。
  2. 排序:排序取决于有符号或无符号的规范。

此代码可以使用排序条件来标识整数:

char a = 0;
a--;
if (0 < a)
    printf("unsigned");
else
    printf("signed");

如果这解释了一种不同,那就是一个负数,另一个负数。这对这篇文章很有帮助。
丹尼尔·杰克逊

@DanielJackson不清楚您说什么。根据编译器的不同,一个char可以被认为是负数或正数。代码的输出取决于编译器选择什么,这显示了有符号和无符号之间的差异。
Minimus Heximus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.