YoungLee的手账

YoungLee的手账

C中的溢出问题

Dev
28
2024-07-07

C中的溢出问题

今天上课做题时遇到了一个问题,运行下面这段代码时会输出负数

#include <stdio.h>

int main()

{ char c1,c2;

c1=197;

c2=198;

printf("c1=%d,c2=%d\n",c1,c2);

return 0; }

GPT给出的解释是

是这段代码中会输出负数,是因为char类型在C语言中通常被视为有符号字符类型(signed char),它的取值范围是-128到127。因此,当你将大于127的整数赋值给char类型变量时,会发生溢出。

当你将一个整数值赋给char类型的变量时,发生了截断和溢出。char类型通常是有符号字符类型,其范围是-128到127(根据具体的编译器和平台可能有所不同,但通常是这样)。这意味着char类型只能表示这个范围内的整数值,超出这个范围的值将导致溢出,导致结果不是你期望的。

在你的代码中,你给c1c2分别赋值197和198。现在,让我们详细解释为什么会输出-59:

  1. 首先,要理解char的范围是-128到127。
  2. 197和198都超出了这个范围。
  3. 因为char是有符号类型,超出范围的整数值会被解释为带符号整数。
  4. 计算机使用二进制补码表示有符号整数。在二进制补码中,最高位表示符号位,0表示正数,1表示负数。
  5. 当你赋值197给c1时,计算机会将其转换为二进制,但由于最高位为1,表示负数,所以计算机会认为它是一个负数。
  6. 197的二进制表示为11000101(8位二进制),最高位为1,所以c1被解释为负数。
  7. 计算机将负数转换为带符号整数,使用的是二进制补码。在二进制补码中,将负数的绝对值转换为二进制,然后取反并加1。所以,11000101的取反是00111010,再加1得到00111011。
  8. 00111011的十进制值是59,但由于最高位是1,表示负数,所以c1的值被解释为-59。
  9. 同样,当你赋值198给c2时,也会类似地溢出,因此c2的值被解释为-58。

所以,溢出后,c1c2的值分别是-59和-58,这就是为什么会输出负数。

后来研究看了一下,

char变量在C语言中通常被视为有符号字符类型,取值范围是-128到127,超出范围的整数值会被解释为带符号整数,计算机使用二进制补码表示有符号整数,经过补码后就会输出负数。