做《c和指针》课后练习时关于char型溢出的一个疑惑

ARCHER-XIE 2015-09-06 06:24:20
有两个问题
原题是这样的:
编写一个程序,从标准输入读取一些字符,并把它们写到标准输出上。它同时应该计算checksum值,并写在字符的后面。
checksum(检验和)用一个signed char变量进行计算,它初始为-1。当每个字符从标准输入读取时,它的值就被加到checksum中。如果checksum变量产出溢出,那么这些溢出就会被忽略。当所有的字符均被写入后,程序以十进制整数的形式打印出checksum的值,它有可能是负值。注意在checksum后面要添加一个换行符。在使用ASCII码的计算机中,在包含“Hello world!"这几个词并以换行符结尾的文件上运行这个程序应该产生下列输出:
Hello world!
102

我分步打印出了checksum的值,如图:


但是在手动计算过程中发现有一点不符,
71+e的ascii值101是172,因为溢出,转换成二进制10101100取补码再转换成十进制应该是-83,为什么显示的是-84呢?
然后-84+l的ascii值108,正好是24,此时又没有问题,为什么呢?

还有《c和指针》这本书上char型范围是-127到127,但是我们通常不是认为是-128到127吗?
...全文
202 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2015-09-08
  • 打赏
  • 举报
回复
引用 15 楼 lin5161678 的回复:
[quote=引用 14 楼 lm_whales 的回复:]
同一个地方还规定了 -32767是最小 int 是不是 -32768 不合法?[/quote] 他这个新的规定的思想是 正数 负数要对称,至于合不合理,个人认为,应该是各有道理 所谓最小实现,其实就是 char >= 8 Bits ,int >=16Bits,long >=32Bits这一类的 DSP上 char 是 16 Bits 那其实是 相应的 -32768 在这个时候,是个不合法的数 从前DOS下,TC int 是16 Bits 在这个标准下,-32768 就是不合法的 至于具体 -128 或者-32768 在某个系统下,合不合法,取决于 char,int 等整型的长度(Bits数) char 为8Bits 的时候,-128 是不合法的 int(short) 为16 Bits的时候, -32768 是不合法的 int(short) 型 并不是,每个系统都受制于最小范围, 无论如何实现 整型(有符号数) , 而是总有一个数不合法,这个数就是 绝对值最大的负数 最小范围,刚好就把 最小长度中的这个 -32768,-128 等 放到 取值范围之外。
lm_whales 2015-09-08
  • 打赏
  • 举报
回复
引用 15 楼 lin5161678 的回复:
[quote=引用 14 楼 lm_whales 的回复:]
同一个地方还规定了 -32767是最小 int 是不是 -32768 不合法?[/quote] 这么做还有一个很合理的原因 那就是 对负数取绝对值,在数学上,结果一定是正的 而 -32768 ,-128 等数,在该长度正数的取值范围,没法定义绝对值 如果定义为 32768 ,128 这个数二进制 和 -32768 ,-128 值相同,表示的却是负数。 这样 【-32767 ,32767】 就比 【-32768,32767】要严谨一点 同理 【-127,127】 这个范围 比【-128,127】 要严谨一点 当然,这样做,也有他的缺点,就是有一个编码没有用上(-32768 ,-128)
lin5161678 2015-09-07
  • 打赏
  • 举报
回复
引用 12 楼 lm_whales 的回复:
问题是 一般实现,也都是 -127 ~127 而不是 -32767 ~ 32767
那又如何? 反正 这也不能说明 -128 就是 非法啊
lin5161678 2015-09-07
  • 打赏
  • 举报
回复
引用 14 楼 lm_whales 的回复:
同一个地方还规定了 -32767是最小 int 是不是 -32768 不合法?
lm_whales 2015-09-07
  • 打赏
  • 举报
回复
引用 13 楼 lin5161678 的回复:
[quote=引用 12 楼 lm_whales 的回复:] 问题是 一般实现,也都是 -127 ~127 而不是 -32767 ~ 32767
那又如何? 反正 这也不能说明 -128 就是 非法啊 [/quote]不能如何,只是不被认可而已 连 标准库里面都改掉了, 你写 -128 在某些系统上可能会警告,或者直接报错,如此而已。
lm_whales 2015-09-06
  • 打赏
  • 举报
回复
引用 10 楼 lin5161678 的回复:
[quote=引用 9 楼 lm_whales 的回复:] [quote=引用 6 楼 adlay 的回复:] [quote=引用 3 楼 lm_whales 的回复:] char型范围是-127到127 是这样的 -128 这个数值,已经溢出了 最高位同时表示 符号,和值 0x80 二进制为 1000 0000 本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128 早期char型范围,确实是 -128 ~127 如今已经改为 -127 ~127了 -128 应该表示为 -127 - 1 其实还是 0x80
如果真如你所的,0x80 表示 -127,那 0x81 怎么办? 也表示 -127? 两个不同的数变了成同一个数,那面对 char x = -127 的时候,内存里面该如何存储这个值才能符合写的人的预期?世界都乱套了。[/quote] -127 ~127 是表数范围 即 char 值只有 -127 ~127 -128 =0x80 是非法数值 不在 char 表示范围 char 的范围是 负数 [0x81 0xFF] , 0,正数 [1~ 0x7F] 正好是 【-127 ~ -1】,0,【1,127】 所以正好是 【-127,127】 0x80 正好不在这个范围,所以是个非法数 [/quote]说错了 不是非法数 标准要求-127~127 说的是最小范围 只要比这个范围大 喜欢实现为 -32768 ~ 32767 也是完全没问题的 都是合法的[/quote] 问题是 一般实现,也都是 -127 ~127 而不是 -32767 ~ 32767
lm_whales 2015-09-06
  • 打赏
  • 举报
回复
C新标准(其实不新,早就是老标准了) char 范围确实是 【-127,127】 但是 char(8Bits 整数) 也确实可以表示 0x80 char c =0x80; /* 也可以改为 char c =128; */ printf ("%d",c);不能说明问题,因为 char 参数在这里 按照 int 传递。这里有类型提升。 即便新标准,hhd 格式。 printf("%hhd",c);也不能说明什么问题。
lin5161678 2015-09-06
  • 打赏
  • 举报
回复
引用 9 楼 lm_whales 的回复:
[quote=引用 6 楼 adlay 的回复:] [quote=引用 3 楼 lm_whales 的回复:] char型范围是-127到127 是这样的 -128 这个数值,已经溢出了 最高位同时表示 符号,和值 0x80 二进制为 1000 0000 本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128 早期char型范围,确实是 -128 ~127 如今已经改为 -127 ~127了 -128 应该表示为 -127 - 1 其实还是 0x80
如果真如你所的,0x80 表示 -127,那 0x81 怎么办? 也表示 -127? 两个不同的数变了成同一个数,那面对 char x = -127 的时候,内存里面该如何存储这个值才能符合写的人的预期?世界都乱套了。[/quote] -127 ~127 是表数范围 即 char 值只有 -127 ~127 -128 =0x80 是非法数值 不在 char 表示范围 char 的范围是 负数 [0x81 0xFF] , 0,正数 [1~ 0x7F] 正好是 【-127 ~ -1】,0,【1,127】 所以正好是 【-127,127】 0x80 正好不在这个范围,所以是个非法数 [/quote]说错了 不是非法数 标准要求-127~127 说的是最小范围 只要比这个范围大 喜欢实现为 -32768 ~ 32767 也是完全没问题的 都是合法的
lm_whales 2015-09-06
  • 打赏
  • 举报
回复
引用 6 楼 adlay 的回复:
[quote=引用 3 楼 lm_whales 的回复:] char型范围是-127到127 是这样的 -128 这个数值,已经溢出了 最高位同时表示 符号,和值 0x80 二进制为 1000 0000 本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128 早期char型范围,确实是 -128 ~127 如今已经改为 -127 ~127了 -128 应该表示为 -127 - 1 其实还是 0x80
如果真如你所的,0x80 表示 -127,那 0x81 怎么办? 也表示 -127? 两个不同的数变了成同一个数,那面对 char x = -127 的时候,内存里面该如何存储这个值才能符合写的人的预期?世界都乱套了。[/quote] -127 ~127 是表数范围 即 char 值只有 -127 ~127 -128 =0x80 是非法数值 不在 char 表示范围 char 的范围是 负数 [0x81 0xFF] , 0,正数 [1~ 0x7F] 正好是 【-127 ~ -1】,0,【1,127】 所以正好是 【-127,127】 0x80 正好不在这个范围,所以是个非法数
ARCHER-XIE 2015-09-06
  • 打赏
  • 举报
回复
引用 4 楼 adlay 的回复:
补码表示的数的绝对值是 取反 + 1, 10101100 按位取反后是 83,再加 1 就是 84 了。同理,0x80 表示的有符号数也是 -128.
这里确实忘记加1了,无语,这么弱智的错误居然也会犯。。
ARCHER-XIE 2015-09-06
  • 打赏
  • 举报
回复
引用 3 楼 lm_whales 的回复:
char型范围是-127到127 是这样的 -128 这个数值,已经溢出了 最高位同时表示 符号,和值 0x80 二进制为 1000 0000 本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128 早期char型范围,确实是 -128 ~127 如今已经改为 -127 ~127了 -128 应该表示为 -127 - 1 其实还是 0x80
赞~\(≧▽≦)/~ 解释的很清楚
www_adintr_com 2015-09-06
  • 打赏
  • 举报
回复
引用 3 楼 lm_whales 的回复:
char型范围是-127到127 是这样的 -128 这个数值,已经溢出了 最高位同时表示 符号,和值 0x80 二进制为 1000 0000 本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128 早期char型范围,确实是 -128 ~127 如今已经改为 -127 ~127了 -128 应该表示为 -127 - 1 其实还是 0x80
如果真如你所的,0x80 表示 -127,那 0x81 怎么办? 也表示 -127? 两个不同的数变了成同一个数,那面对 char x = -127 的时候,内存里面该如何存储这个值才能符合写的人的预期?世界都乱套了。
www_adintr_com 2015-09-06
  • 打赏
  • 举报
回复
引用 3 楼 lm_whales 的回复:
char型范围是-127到127 是这样的 -128 这个数值,已经溢出了 最高位同时表示 符号,和值 0x80 二进制为 1000 0000 本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128 早期char型范围,确实是 -128 ~127 如今已经改为 -127 ~127了 -128 应该表示为 -127 - 1 其实还是 0x80
这个很好验证

	char x = 0x80;
	printf("%d\n", x);
它就是 -128
www_adintr_com 2015-09-06
  • 打赏
  • 举报
回复
补码表示的数的绝对值是 取反 + 1, 10101100 按位取反后是 83,再加 1 就是 84 了。同理,0x80 表示的有符号数也是 -128.
lm_whales 2015-09-06
  • 打赏
  • 举报
回复
char型范围是-127到127 是这样的 -128 这个数值,已经溢出了 最高位同时表示 符号,和值 0x80 二进制为 1000 0000 本来应该是 128 但是 符号位是负值 实际应该表示为 1 1000 0000 ,不是8 位数数了 所以是 -128 早期char型范围,确实是 -128 ~127 如今已经改为 -127 ~127了 -128 应该表示为 -127 - 1 其实还是 0x80
baidu_31102583 2015-09-06
  • 打赏
  • 举报
回复
新人看看 哈哈
  • 打赏
  • 举报
回复
checksum(检验和)用一个signed char变量进行计算,它初始为-1 -128~127

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧