有符号整型和无符号整型的区别是什么?
您可能已经知道,int在内部以二进制形式存储。通常 int包含32位,但在某些环境中可能包含16或64位(或者甚至是一个不同的数字,通常但不一定是2的幂)。
int
但是对于这个例子,让我们看看4位整数。很小,但是对于演示来说很有用。
因为这样一个整数有四个位,所以它可以假定16个值中的一个; 16是2的四次方,或者2乘2乘2乘2。这些价值观是什么?答案取决于这个整数是 signed int还是 unsigned int。对于 unsigned int,该值永远不会为负; 没有与该值相关联的符号。下面是4位 unsigned int的16个可能值:
signed int
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
下面是4位 signed int的16个可能值:
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 int来说,这个位被称为“符号位”。
1
有时我们事先知道存储在给定整数变量中的值总是正的——例如,当它被用来只计数时。在这种情况下,我们可以将变量声明为无符号的,如 unsigned int num student;。使用这样的声明,允许的整数值范围(对于32位编译器)将从 -2147483648到 + 2147483647到0到4294967295。因此,将一个整数声明为无符号的几乎是它可以保存的最大值大小的两倍。
unsigned int num student;
在外行人的术语中,一个无符号整数是一个不能为负的整数,因此它可以假设一个更大的正值范围。有符号整数是一个整数,它可以是负数,但是具有较低的正值范围,以换取它可以假设的更多负值。
int和 unsigned int是两种不同的整数类型。(int也可以被称为 signed int,或者仅仅是 signed; unsigned int也可以被称为 unsigned。)
signed
unsigned
顾名思义,int是 签了整数类型,而 unsigned int是 没签名整数类型。这意味着 int能够表示负值,而 unsigned int只能表示非负值。
C 语言对这些类型的范围提出了一些要求。int的范围必须至少为 -32767。.+32767和 unsigned int的范围必须至少是 0。.65535.这意味着这两种类型都必须至少为16位。它们在许多系统上是32位的,甚至在某些系统上是64位的。由于大多数现代系统使用二进制补语表示,int通常有一个额外的负值。
-32767
+32767
0
65535
也许最重要的区别是有符号算术和无符号算术的行为。对于已签署的 int,溢出未定义行为为。对于 unsigned int,没有溢出; 任何产生超出类型范围的值的操作都会绕过,例如 UINT_MAX + 1U == 0U。
UINT_MAX + 1U == 0U
任何整数类型,无论是有符号的还是无符号的,都建模无限数学整数集的子范围。只要处理的是类型范围内的值,一切都可以正常工作。当接近类型的下界或上界时,会遇到不连续性,并可能得到意想不到的结果。对于有符号整数类型,问题仅出现在非常大的负值和正值上,超过 INT_MIN和 INT_MAX。对于无符号整数类型,非常大的正值 而且是零会出现问题。这可能是一个错误的来源。例如,这是一个无限循环:
INT_MIN
INT_MAX
for (unsigned int i = 10; i >= 0; i --) { printf("%u\n", i); }
因为 i是 一直都是大于或等于零; 这就是无符号类型的本质。(在循环内部,当 i为零时,i--将其值设置为 UINT_MAX。)
i
i--
UINT_MAX
在实践中,存在两个不同之处:
cout
printf
此代码可以使用排序条件识别整数:
char a = 0; a--; if (0 < a) printf("unsigned"); else printf("signed");
char在某些编译器中被认为是 signed,在其他编译器中被认为是 unsigned。上面的代码使用排序条件确定在编译器中考虑哪一个。如果 a是无符号的,在 a--之后,它将大于 0,但如果它是 signed,它将小于零。但是在这两种情况下,a的位表示是相同的。也就是说,在这两种情况下,a--对位表示进行相同的更改。
char
a
a--