自从我开始用 C 编程已经有一段时间了,但是我仍然对unsigned
. 如果我们编译这段代码:
#include <stdio.h>
int main(int argc, char **argv)
{
unsigned int x = -1;
return 0;
}
gcc 和 VC++ 都不会引发任何错误,甚至不会发出关于将负数与unsigned
.
我的问题是它unsigned
做任何内部工作还是只是向程序员暗示这个值不应该是负数?
这不仅仅是一个提示。以下两个片段的行为应该不同:
签名整数:
int x = -1;
printf("%d\n", x > 0); // prints 0
无符号整数:
unsigned int x = -1;
printf("%d\n", x > 0); // prints 1
你可能会想出另外 5 个签名很重要的例子。例如,与操作员一起右移>>
。
用于-Wsign-conversion
获得警告gcc
。
在gcc
4.7.1 中,-Wsign-conversion
既不是也不-Wall
属于 -Wextra
.
另请注意,C 标准不需要对此初始化发出警告。
unsigned
不是static
,或extern
等限定符。它是类型的一部分。const
inline
int
并且unsigned int
是两种完全不同的类型。你永远不会找到一个unsigned int
可以容纳负数的。还要注意int
和signed int
是完全相同的类型。对于 来说,这是一个稍微不同的故事char
,但我会再讲一遍。
分配-1
给一个无符号整数是一个常见的技巧,可以将它设置为它可以容纳的最大值。
尝试通过以下方式在 gcc 中启用警告:gcc -Wall -o out input.c
unsigned int
和 normal之间的另一个区别int
:int
使用 4 字节的范围:–2,147,483,648 到 2,147,483,647,unsigned
使用 4 字节的范围:0 到 4,294,967,295。您不必存储有关符号(最高位)的信息,因此您可以分配更大的值并且应用程序将正常工作。
unsigned
会影响整数溢出、比较和按位移位行为。这不仅仅是一个“提示”,它不应该是负面的。
((unsigned int) -1)
等价于(UINT_MAX)
( <limits.h>
),因为从负值到无符号值的转换保证通过模运算完成。
C11 § 6.3.1.3 有符号和无符号整数
2 否则,若新类型为
unsigned
,则在新类型所能表示的最大值的基础上反复加减一,直到该值在新类型的范围内。
用于计算的内部(机器级)指令有带符号和无符号版本,例如乘法mul
(用于无符号)和imul
(有符号)。当您将变量声明为无符号或有符号时,编译器会选择它们。