[英]ASCII value is greater than 127
#include <stdio.h>
int main() {
char c = 125;
c = c + 10;
printf("%d", c);
return 0;
}
此代码的 output 是-121
。
这个 output 怎么是-121
? 你能解释一下吗?
如果我用c
添加100
而不是10
那么 output 是-31
。 为什么?
在 C 语言中, char
类型是integer类型,能够表示语言本身所需的所有字符。 该标准没有指定它是有符号还是无符号类型。 在看到 output 之后,我可以猜测您的系统使用大小为 8 位(7 个值位和一个符号位)的有符号字符,并在 2 补码中表示负值。
所以(作为 int)125 + 10 = 135。135 > 128 所以实际值为 135 - 256 = -121。
(在两个补码模式下,数字只是包裹在 2**SIZE_IN_BITS...)
它的工作原理是编译器中的char
类型是 8 位宽的有符号类型,并使用称为二进制补码的系统表示 integer 值。
在这个系统中,正值 go 以二进制形式从 0 到 127,如下所示:
00000000 0
00000001 1
00000010 2
00000011 3
... .
01111111 - 127
在下一个增量时,最高位翻转为 1:我们得到10000000
。 然后随后的二进制值在二进制补码下被解释为负数:
10000000 128 -128
10000001 129 -127
10000010 130 -126
...
11111111 255 -1
中间一列,从 128 继续往上计数,显示 8 位数据的无符号解释; 它只是一直向 255 计数。这将是unsigned char
类型的行为。
右列显示负数,是对完全相同的位模式的二进制补码解释。 这反而涵盖了从 -128 到 -1 的负整数范围。
现在,当我们执行c + 10
时, C 会发生什么?
首先,根据 C 语言的规则,将char
类型的c
值提升为int
类型,其范围更大。 因此int
值 125 与int
值 10 相加,得到int
值 135。
接下来发生的是c
被分配了该值,就像c = 135
一样。 但是135
它不在范围内; char
只上升到127
。 实现定义的行为随之而来。 通过丢弃位以某种方式强制适应135
值。
用于二进制补码机器的 C 编译器(即地球上几乎所有的编译器)将更宽的 integer 值截断为更窄的值,只需截断值的底部位以适应较小的类型。
所以,135的二进制表示是这样的。
10000111
更准确地说,假设int
是 32 位宽。 那么int
值135的表示为:
00000000000000000000000010000111
通过砍掉前 24 位,将其转换为 char,留下后 8 位:
------------------------10000111
所以我们最终得到
10000111
在char
类型中。 但那是什么? 参考我们的原始表格,我们可以再添加几行:
10000000 128 -128
10000001 129 -127
10000010 130 -126
10000011 131 -125
10000100 132 -124
10000101 133 -123
10000110 134 -122
10000111 135 -121 <----
...
11111111 255 -1
还有-121。
char
类型在 memory 中表示为一个byte
(大部分时间为 8 位),因此它可以表示从-128
到+127
的值。 如果您尝试在 memory 中存储更大的值,则会导致溢出,结果与预期不符。
这是一个很好的视频,解释了什么是溢出。
char 是 8 位的一个字节。 一位用于符号,7 位供您使用。
"char" 范围是:char ==> -128 ~ 127
static_cast<char>(c+1) = 126
static_cast<char>(c+2) = 127
static_cast<char>(c+3) = -128
如果您使用“unsigned char”,则正范围会增加。
无符号字符 ==> 0 ~ 255
static_cast<unsigned char>(c+3) = 128
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.