【问题标题】:Why data overflow in a `char` data type causes wrappping the value within its range?为什么 `char` 数据类型中的数据溢出会导致将值包装在其范围内?
【发布时间】:2020-07-12 04:11:33
【问题描述】:

我最近遇到this的问题和@chux - Reinstate Monica给出的答案。

从他们的答案中引用行,“这是实现定义的行为。分配的值可能是 0 或 1 或 2...通常,通过加/减来环绕(“修改”)值256 直到在范围内。100 + 100 -256 --> -56。"

代码:

#include <stdio.h>
int main(void)
{
 char a = 127;
 a++;
 printf("%d", a);
 return 0;
}

输出: -128


在大多数 C 编译器中,char 类型采用 1 Byte 大小,严格来说,我假设它是 16 位系统,char 采用 1 Byte

a = 127时,它在计算机内部的二进制表示是0111 1111,加1应该得到值

0111 1111 + 0000 0001 = 1000 0000

等于-0(考虑到有符号数表示,其中最左边的位表示0 = + and 1 = -)那么为什么输出等于-128

是因为“整数提升规则”吗?我的意思是,对于这个表达式a + 1a+ 操作之前被转换为int (2 Bytes),然后它在内存中的二进制表示变为1111 1111 1000 0000,它等于-128,并且对输出有意义-128。但是我的这个假设与 Chux-Reinstate-Monica 关于包装值的引用行相冲突。

【问题讨论】:

标签: c char


【解决方案1】:

1000 0000 等于 -0...

Ones' complement 有 -0,但大多数计算机使用 two's complement,但没有。

two's complement 符号中,最左边的位代表-(coefficient_bit * 2^N-1),即在您的情况下,1000 0000 最左边的位代表-(1 * 2^8-1),它等于-128,这就是输出相同的原因。

您的 char 是一个 8 位有符号整数,在这种情况下 1000 0000 是 -128。我们可以使用GNU extension which allows binary constants 方便地测试 1000 0000 是什么。

char a = 0b10000000;
printf("%d\n", a);    // -128

char,在这个实现中,是一个有符号的 8 位整数。将 1 加到 127 会导致整数溢出到 -128。

整数提升呢?整数提升发生在计算期间,但结果仍然是char。 128 不适合我们有符号的 8 位字符,所以它溢出到 -128。

整数提升由this example演示。

char a = 30, b = 40;
char c = (a * b);
printf("%d\n", c);      // -80

char d = (a * b) / 10;
printf("%d\n", d);      // 120

char c = (a * b); 是 -80,但 char d = (a * b) / 10; 是 120。为什么?不应该是-8吗?这里的答案整数提升。数学以本机整数形式完成,但结果仍必须填充到 8 位字符中。 (30 * 40) 是 1200 即 0100 1011 0000。然后必须将其塞回一个 8 位有符号整数;那是 1011 0000 或 -80。

对于其他计算,(30 * 40) / 10 == 1200 / 10 == 120 非常合适。

【讨论】:

  • 这个答案不能解释我的问题。但谢谢顺便说一句。我已经阅读了它的大部分内容。您介意阅读 @rici 评论吗?
  • @Lucas 我已经阅读了评论线程,rici 也说了同样的话:你得到 -128 因为计算机使用 2 的恭维,而不是 1。抱歉,还有什么无法解释的?
  • @Lucas 我明白了,你需要解释一下 2 的补码。感谢您的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
  • 2016-03-14
  • 2010-11-22
相关资源
最近更新 更多