看stl源码发现这句代码,一时不太明白为何得到Max_possible
constexpr size_t _Max_possible = static_cast<size_t>(-1) / _Ty_size;
所以查了下资料,发现是关于原码、反码、补码的问题。https://blog.csdn.net/qq_48052049/article/details/125994544这篇博客中已经讲述得很清楚了,简单记录一下自己理解,加深印象!
一、原码
一个Byte在计算机中有8位,在一个有符号的Byte中,最高位表示正负, 其余7位表示数据,所以源码表示的范围是1111 1111(-127)到0111 1111(127)。
但是因为原码计算负数, 比如1000 0010(-2) + 1 ,得到的结果是1000 0011(-3),不是正确结果-1。为了解决这个问题, 可以引用反码来解决。
1000 0010
+ 0000 0001
------------
1000 0011
二、反码
定义:正数的反码就是其本身(0000 1111->0000 1111), 负数的反码是符号位不变,数据位取反(1000 1111 -> 1111 0000).
这样可以解决计算负数的问题,比如:1111 1101(-2) + 1= 1111 1110(-1), 得到正确的答案。
1111 1101
+ 0000 0001
-------------
1111 1110
但是在处理跨0的问题上,反码也力有不及, 比如:11111 010(-5) + 0000 0111(7) = 1, 这是错误的:
1111 1010
+ 0000 0111
---------------
0000 0001
三、补码
定义:正数的补码就是其本身, 负数的补码为其反码再加1。
由补码的方式计算1111 1011(-5) + 0000 0111(7):
1111 1011
+ 0000 0111
---------------
0000 0010
最终结果为2。 所以补码能解决上述问题,计算机一般都是采用补码的方式。
四、 总结
这里再引用上述博客中的那张比较直观的表:
十进制 | 原码 | 反码 | 补码 |
---|---|---|---|
+0 | 0000 0000 | 0000 0000 | 0000 0000 |
-0 | 1000 0000 | 1111 1111 | 0000 0000 |
-1 | 1000 0001 | 1111 1110 | 1111 1111 |
-2 | 1000 0010 | 1111 1101 | 1111 1110 |
-3 | 1000 0011 | 1111 1100 | 1111 1101 |
-4 | 1000 0100 | 1111 1011 | 1111 1100 |
-5 | 1000 0101 | 1111 1010 | 1111 1011 |
-6 | 1000 0110 | 1111 1001 | 1111 1010 |
-7 | 1000 0111 | 1111 1000 | 1111 1001 |
... | ... | ... | ... |
-127 | 1111 1111 | 1000 0000 | 1000 0001 |
-128 | 无 | 无 | 1000 0000 |
所以在计算机中,一个有符号的Byte表示的十进制数范围是[-128, 127]。
回到最初的问题static_cast<size_t>(-1),这里中size_t是一个无符号int, 本人电脑内存中表示4个byte,-1用反码在内存中的表示就是1111 1111 .......1111, 把他赋值给一个无符号Int就是表示最大值4294967295, 这里Max_possible就能说得通了。