我正确地说无符号整数和有符号整数之间的区别是:
- 无符号整数可以容纳更大的正值,但不能存储负值。
- 无符号整数使用最高位作为值的一部分,而有符号版本使用最高位来标识数字的正负性。
- 有符号整数可以容纳正数和负数。
还有其他区别吗?
无符号整数比有符号整数更容易陷入特定的陷阱。这个陷阱源于一个事实,即虽然上面的1和3是正确的,但两种类型的整数都可以被赋予超出其“容量”范围的值,并且它将被静默转换。
unsigned int ui = -1;
signed int si = -1;
if (ui < 0) {
printf("unsigned < 0\n");
}
if (si < 0) {
printf("signed < 0\n");
}
if (ui == si) {
printf("%d == %d\n", ui, si);
printf("%ud == %ud\n", ui, si);
}
signed < 0
-1 == -1
4294967295d == 4294967295d
在嵌入式系统编程时,必须使用无符号整数。在循环中,如果不需要有符号整数,则使用无符号整数将节省设计此类系统所需的安全性。
...然后发生的事情是它实际上有点奏效:如果您在之后有一个进位(环绕),则只需将数字加一,然后考虑0…0和1…1都表示0。这就是补码Ones'_complement。 但是,这样做,您必须为符号保留一位。从技术上讲,您可以表示从-(2^(n-1)-1) ≤ n ≤ 2^(n-1)-1的值 它们是:(2^n)-1(0的两种表示)。在这种表示中,您只需交换所有位以否定数字。
然后更聪明的人告诉我们:“如果我们认为在对数字取反时总是有一个环绕呢?”……这意味着在交换位之后加上一。你就得到了2的补码Two's complement。使用它,你的零只有一个表示,而且你可以再次表示2^n个数字(其中2^(n-1) ≤ n ≤ 2^(n-1)-1)。此外,a-b
的计算实际上只是a+(-b)
,它只需要两种操作:add(a, add(swap(b), 1)))
2的补码的另一个好处是,加法算法与无符号算法相同。因此,你可以获得相同的属性,并使用相同的硬件来执行两者。这就是为什么它是大多数计算机中使用的表示形式。
简而言之,signed和unsigned可以表示相同数量的数字,但范围不同,现在你知道了具体是哪些以及为什么。有关所获得的代数结构的更多详细信息,请阅读此回答:https://dev59.com/YnVC5IYBdhLWcg3wliKe#23304179 然后根据上下文使用其中之一(请注意,对于某些操作,如<
,强制转换时处理方式不同:((signed) -1) < 5
但((unsigned) -1) > 5
)。