EOF 的定义值是(-1),而 char 是一个 unsigned short,正常吗?

2015-11-11 22:31:24 +08:00
 ru20150601
以前没注意过这个,刚才在树莓派写 c 发现了这个问题。 stdlib.h 定义了 EOF 是(-1 ),实际输出也验证了这点。 char 值的范围测试发现是 0-255 。

是不是我就没法写(c=getchar())!=EOF 这种代码了?
3503 次点击
所在节点    程序员
17 条回复
Mangle
2015-11-11 22:36:38 +08:00
所以 k&r c 里面这个 c 的定义的是 int 类型啊
adadada
2015-11-11 22:44:19 +08:00
getchar() 的返回类型是 int
ru20150601
2015-11-11 22:48:42 +08:00
@Mangle
额,我是想搞清楚到底是我安了错误的 package ,还是树莓派自身的问题啊。

另外我刚才看了一下 limits.h 文件,CHAR_MAX 是 127 , CHAR_MIN 是(-128 ),为啥实际编译出来变成了 0-255 了呢?
auser
2015-11-11 23:05:49 +08:00
char 是 unsigned 或者 signed 可以由编译器指定默认的或者通过编译选项改变。
char 所占的内存,不论是用无符号打印出来和有符号打印出来,内存里的数值是一样的。
printf 打印的时候,如果%后边的字符串指定的和对应参数不符,是会发生强制转换的。
char 和 EOF 比较的时候,是有强制转换发生的。
ru20150601
2015-11-11 23:22:04 +08:00
@auser
我已经弄明白怎么回事了。 K&R 中的例子经常是 while(((c=getchar())!=EOF) 什么的,我一直以为 c 是 char ,刚才确认了一遍,此书一直将 c 声明为 int 。唉,都怪我看书不认真。
alexapollo
2015-11-11 23:36:14 +08:00
getchar() 是 int 一直是个大坑
wsy2220
2015-11-11 23:51:38 +08:00
@alexapollo getchar()返回 int 是有道理的,因为要保证 EOF 不是任意一个正常的字符的值。
xieyudi1990
2015-11-12 04:59:59 +08:00
@wsy2220 C 里之所以大部分都返回 int (一般即机器字长, 即使用不到这个范围), 是因为没有必要去限制: 计算机都是按字对齐访存的 (比如几乎所有 RISC 都不支持单指令非对齐访问). 稍微学过体系结构的应该都清楚这点. 这点我记得 "C 和指针" 也有讲到.

这个 EOF 即使是 int, 其低 8 位用补码表示依然是 "-1". 这两者 ("返回 int" 和 "EOF 不是任意一个正常的字符的值") 是没有关系的 (即使返回的是 char, EOF 也不是一个正常的字符的值).
Arthur2e5
2015-11-12 06:24:33 +08:00
> @xieyudi1990

0xFF 这个字节在流中就是可以自然产生的,
Arthur2e5
2015-11-12 06:26:13 +08:00
@Arthur2e5 糟了,手抖严重。

> (即使返回的是 char, EOF 也不是一个正常的字符的值).

按这个想法想的话很危险啊,顺手 shell 跑个 printf \\xff2333 | ./yourprog 就可以给报个 bug 了。况且不是一般字符你也要问问编码啊。
xieyudi1990
2015-11-12 06:55:23 +08:00
@Arthur2e5 C 里面也没有你说的这种东西, 你说的那个概念应该和 LZ 的问题不再一个层次.

不管你在计算机上做任何事, 这东西总归会到 "软件" 的最底层 (ISA, RTL). 那一层默认就是这么处理数据的, 所以才有 LZ 观察到的这个现象.
thinkIn
2015-11-12 07:22:34 +08:00
K&R 中并未指定 char 是否有符号。只保证可打印字符为正值。
wizardoz
2015-11-12 09:11:02 +08:00
首先 getchar() 返回的是 int
其次, char 的范围是-128 - 127

正确的做法是先取到 int 中,判断是否为-1,如果不为-1,再赋值给 char
Arthur2e5
2015-11-16 13:10:35 +08:00
@xieyudi1990

这和最底层没有半点关系,只不过是对认为这世上 getchar 读不到 \xFF 的反驳。 Unix 的所谓“字符”流就是二进制数据流,不小心点怎么行?
xieyudi1990
2015-11-16 13:54:22 +08:00
@Arthur2e5 你没看懂我的意思. Unix 为什么这么设计? C 为什么设计? 我说的就是根源.
xieyudi1990
2015-11-16 14:04:42 +08:00
@Arthur2e5

这一点表面上来看, getchar 的 manpage 以及 C 的文档已经解释了. 我 LS 已经解释得很彻底了, 所以结合我的经验谈下为什么这么做.

题主的问题是 "(c=getchar())!=EOF" 里能不能这么判断, 而不是什么能不能读到 0xff. 所以你所说的, 从一开始到最后和这个问题完全不着边际.

不仅仅是 'Unix 的所谓“字符”流就是二进制数据流', 而是 你在计算机上所遇到的一切东西都可以是二进制流. 感觉你不是学计算机的.
Arthur2e5
2015-11-21 00:31:15 +08:00
@xieyudi1990 我只是在吐槽题主的那一句“ EOF 也不是一个正常的字符的值)”啊,你明明也看得到我 cite 的。

> 你在计算机上所遇到的一切东西都可以是二进制流

题主语义下的“字符”已经是指一般的 text 而不是一坨二进制了。对于确定是 text 的东西处理方式不同又不是很少见,例如 git autocrlf 和 ftp text mode 。

吵这种事情很有意思吗?

> 感觉你不是学计算机的

你可以来高中开一个计算机专业。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/235469

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX