关于 EOF 和 ÿ 的困惑

Confusion about EOF and ÿ

在我的 Windows 上的 GCC 中,EOF 的值是 -1。我注意到 'ÿ' 的值也是 -1。所以我做了以下实验,但我对结果完全感到困惑。

int main() {
    
    int a = 'ÿ';
    if (a == EOF) {
        putchar('a');
        putchar(a);
    }

    char b = 'ÿ';
    if (b == EOF) {
        putchar('b');
        putchar(b);
    }

    putchar('\n');

    int c;
    if ((c = getchar()) != EOF) {
        putchar('c');
        putchar(c);
    }

    char d;
    if ((d = getchar()) != EOF) {
        putchar('d');
        putchar(d);
    }
}

结果是

aÿbÿ  // a == EOF b == EOF
ÿÿ    //My input for int c and char d
cÿ    // c != EOF

我的问题是: 1. 当我直接将'ÿ'赋值给一个变量时,无论类型是int还是char,都等于EOF。但是当我从 stdin 将 'ÿ' 分配给 int c 时,结果发现 c 不等于 EOF。这里发生了什么? 2.如果文件中有'ÿ',系统如何区分'ÿ'EOF

'ÿ' 是数字 255 的字符表示。它的值为 char literal 是 -1.

255-1都具有相同的8位表示(11111111),这取决于它是被解释为有符号值还是无符号值。 char 是有符号的,因此它作为 char 的值是 -1.

当它被分配给一个 char 变量时,它按原样存储。
当它被分配给一个 int 变量时,该值被提升为 int 并且这不会改变它的值,它只是使用更多的位(4 个字节)来表示。

顺便说一句,-1也是EOF的值(但你应该在代码中始终使用常量EOF,不要依赖它的数值)。


getchar()return一个int;对于 'ÿ' 它 returns 255.

当它被分配给一个 int 时,值被保留。

当它分配给 char 时,行为未定义(因为 char 变量的可能值范围是 -128..+127) .
似乎您的编译器选择将 255 最右边的 8 位存储到 char 变量中,并且由于 char 已签名,该值被解释为 -1.

How does the system distinguish between 'ÿ' and EOF if there's a 'ÿ' in the file?

getchar()fgetc()/getc()等读取字符的函数returnint。这意味着当成功时它们总是 return 值介于(包括)0255 之间,当到达文件末尾时它们总是 EOF (具有负值)。

EOF的值为负数,不能与'ÿ'混淆。

C 程序有一个执行字符集,这决定了字符文字如何映射到整数值。

您的程序似乎正在使用 iso-8859-1 作为执行字符集进行编译。在我的电脑上,gcc 的默认值是 utf-8,其中 'ÿ' 映射到“多字符常量”50111。对于 iso-8859-1,gcc 将其映射到 -1。我必须使用标志 -fexec-charset=iso-8859-1 来重现您所看到的内容。

当您从文件(或标准输入)中读取时,您将获得操作系统提供给您的任何字节(解释为无符号字符)。 stdin 和文件的编码通常独立于执行字符集。

您观察到的是执行字符集是 iso-8859-1 映射到范围 -128 到 127(而不是通常的 0 到 255),大概是因为 char在您的编译器上签名,因此可以表示执行字符集中的每个值。 stdin 的编码似乎也是 iso-8859-1,除了它使用通常的 0 到 255。在你的问题中的情况 (d) 中,值 255 被分配给 char(可能已签名, 从 -128 到 127), gcc 正在包装它。

总结:

  • (a) 将 -1 分配给 a
  • (b) 将 -1 分配给 b
  • (c) 将 255 分配给 c
  • (d) 将 255 转换为 char,结果为 -1。这个 -1 赋值给 d.