表示char是一个8位变量,只能保存2^8 = 256个值,因为声明是char ch,ch是一个signed变量,也就是说它可以存储127负值和正值。当您要求超过 127 时,该值从 -128 开始。
把它想象成一些街机游戏,你从屏幕的一侧移动到另一侧:
ch = 50;
-----> 50 is stored
|___________________________________|___________| since it fits
-128 0 50 127 between -127
and 128
ch = 129;
--- 129 goes over
--> 127 by 2, so
|__|____________________________________________| it 'lands' in
-128 -127 0 127 -127
但是!!你不应该依赖它,因为它是未定义的行为!
为了纪念 Luchian Grigore,以下是正在发生的事情的位表示:
char 是一个保存 8 位或一个字节的变量。因此,我们有 8 个 0 和 1 努力代表您想要的任何值。如果char 是signed 变量,它将表示它是正数还是负数。您可能读过有关表示符号的一位,这是对真实过程的抽象;事实上,它只是在电子领域实施的首批解决方案之一。但是这样一个微不足道的方法有一个问题,你会有2种方式来表示0(+0和-0):
0 0000000 -> +0 1 0000000 -> -0
^ ^
|_ sign bit 0: positive |_ sign bit 1: negative
保证不一致!!因此,一些非常聪明的人想出了一个称为 Ones' Complement 的系统,它将一个负数表示为其正数的否定(非运算):
01010101 -> +85
10101010 -> -85
这个系统...有同样的问题。 0 可以表示为 00000000 (+0) 和 11111111 (-0)。然后出现了一些更聪明的人,他们创建了二的补码,它将保留早期方法的否定部分,然后添加 1,因此删除了那个讨厌的 -0 并为我们的范围提供了一个闪亮的新数字:-128!。那么我们的范围现在看起来如何?
00000000 +0
00000001 +1
00000010 +2
...
01111110 +126
01111111 +127
10000000 -128
10000001 -127
10000010 -126
...
11111110 -2
11111111 -1
因此,当我们的小处理器尝试将数字添加到我们的变量时,这应该可以让您了解发生了什么:
0110010 50 01111111 127
+0000010 + 2 +00000010 + 2
------- -- -------- ---
0110100 52 10000001 -127
^ ^ ^
|_ 1 + 1 = 10 129 in bin _| |_ wait, what?!
是的,如果您查看上面的范围表,您可以看到最多 127 (01111111) 二进制文件很好而且花花公子,没有什么奇怪的事情发生,但是在第 8 位设置为 -128 (@987654337 @) 解释的数字不再保持其二进制大小,而是保持二进制补码表示。这意味着,二进制表示,变量中的位,1 和 0,我们心爱的char 的心脏,确实有一个 129... 它在那里,看看它!但是邪恶的处理器读取到微不足道的 -127 导致变量 HAD 为signed 破坏了它在欧几里得空间中通过实数线进行臭味移位的所有积极潜力。