V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ru20150601
V2EX  ›  程序员

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

  •  
  •   ru20150601 · 2015-11-11 22:31:24 +08:00 · 3484 次点击
    这是一个创建于 3094 天前的主题,其中的信息可能已经有所发展或是发生改变。
    以前没注意过这个,刚才在树莓派写 c 发现了这个问题。 stdlib.h 定义了 EOF 是(-1 ),实际输出也验证了这点。 char 值的范围测试发现是 0-255 。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    吵这种事情很有意思吗?

    > 感觉你不是学计算机的

    你可以来高中开一个计算机专业。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   851 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 19:55 · PVG 03:55 · LAX 12:55 · JFK 15:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.