关于有符号数和无符号数的一些重要知识点,包括它们在内存中的存储方式、互相转换、越界计算等。
有符号数的表示法
大家肯定都知道,对于有符号数,数据类型的最高位用于标示数据的符号,最高位为1表示负数,最高位为0表示正数,那么今天我们主要就此讨论一个问题:在计算机内部具体是如何表示有符号数呢?
在计算机内部是通过补码的方式来表示有符号数的。
–正数的补码为正数本身
–负数的补码为负数的绝对值各位取反后再加1
举几个例子:
8位整数5的补码:0000 0101
8位整数-7的补码:1111 1001
|-7| ==> 7 ==> 0000 0111 ==> 1111 1000 ==> 1111 1001
16位整数20的补码:0000 0000 0001 0100
16位整数-13的补码:1111 1111 1111 0011
|-13| ==> 13 ==> 0000 0000 0000 1101 ==> 1111 1111 1111 0010
==> 1111 1111 1111 0011
无符号数的表示法
在计算机内部用原码表示无符号数。
对于固定长度的无符号数:
–MAX_VALUE + 1 -> MIN_VALUE
–MIN_VALUE - 1 -> MAX_VALUE
不要混用有符号数和无符号数进行运算
当有符号数和无符号数混用进行计算时,有符号数会被转换成无符号数进行计算,计算结果为无符号数,这会导致与预期不符的结果。
在循环条件中使用无符号数要小心
由于无符号数总是大于等于0的,因此在循环中,若使用无符号数作为控制循环是否继续进行的条件变量,要特别小心,避免造成无限循环和永远无法进入循环的情况。
有符号数越界计算
在笔试题中经常会遇到含有诸如signed char a = 224,signed cha b = -10000的题目,它通常以此给出一些选项,让你判断正误,这类题的关键是正确计算越界的有符号数的正确值,为了节省时间,总结下快速计算的公式,原理就不说了,纯粹是为了应试的东西。
我们已经知道:
8位signed char的取值范围为[-128,127];
32位int的取值范围为[-2147483648, 2147483647];
假设值为a的数据其数据类型大小为b位:
(1) 若a为右越界,则实际值 = a - 2^b * n,n根据a的大小确定;
(2) 若a为左越界,则实际值 = a + 2^b * n,n根据a的大小确定;
以上面提到的signed char a = 224,signed cha b = -10000为例:
a > 127为右越界,其实际值 = 224 - 256 * 1 = -32;
b < -128为左越界,其实际值 = -10000 + 256 * 39 = -10000 + 9984 = -16。