为什么这个C程序输出的字符很奇怪?

6

我有下面这个程序:

#include <stdio.h>

int main()
{
        int ch;
        while( ch = getchar() != '\n') {
                printf("Read %c\n",ch);
        }  
        return 0;
}

无论我输入什么,都会得到以下结果:
Read  

为什么会发生这种情况,那个奇怪的字符是什么?
在Stackoverflow上没有打印出奇怪的字符。你可以在这里看到它:http://ideone.com/EfZHr

1
如果您正在使用gcc,请确保已设置-Wall标志。它报告的许多常见问题之一就是这个。 - JeremyP
3个回答

18

您需要将括号放置为:

while( (ch = getchar()) != '\n')

!=的优先级高于=

while( ch = getchar() != '\n')

等同于:

while( ch = (getchar() != '\n') )

代码读取一个字符并将其与换行符进行比较,然后将比较结果分配给ch。现在比较的结果为0(输入换行符时)或1(输入其他任何内容时)。

你看到的奇怪字符是值为1控制字符,ASCII 1没有可打印符号,所以我猜是shell打印了一个带有值为0001的奇怪字符。

你可以通过将程序输出导入八进制转储(od)来确认:

$ echo 'a' | ./a.out | od -bc         # user entered 'a'
0000000 122 145 141 144 040 001 012
          R   e   a   d     001  \n
here you go  ----------------^


$ echo '\n' | ./a.out | od -bc        # user entered '\n'
0000000

当使用-Wall时,GCC会发出以下警告:

warning: suggest parentheses around assignment used as truth value

1
相同优先级查找参考:D - Marcel Jackwerth

2
C(和 C++)将 while 循环解释为:
while( ch = (getchar() != '\n')) {

因此,ch 获得值 1(表示为 true),这是一个不可打印的字符。您应该使用显式括号来修复优先级:

 while( (ch = getchar()) != '\n') {

啊,确实如此。但这适用于两者 :) - bdonlan

1
ch = getchar() != '\n'

编写此代码将导致意外行为,具体取决于语言的运算符优先级。在C中,=!=之后进行评估,因此ch将为true或false。请尝试:
(ch = getchar()) != '\n'

1
你没有更加优雅的词汇来表达彻底失败吗? - Ben Voigt
我确实不知道为什么昨天选择了那个措辞,但已经更改了。 - Marcel Jackwerth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接