【问题标题】:Are there any common C environments where EOF != -1 or WEOF != -1是否存在 EOF != -1 或 WEOF != -1 的常见 C 环境
【发布时间】:2017-04-04 16:39:39
【问题描述】:

C 标准使用以下语言定义 EOFWEOF

7.21.1 输入/输出 - 简介

头文件<stdio.h>定义了几个宏,并声明了三种类型和许多函数用于执行输入和输出。

...

EOF

它扩展为一个整数常量表达式,类型为 int 和一个负值,由多个函数返回以指示文件结束,即不再有来自流的输入;

...

7.21.1 扩展的多字节和宽字符实用程序 - 简介:

标题<wchar.h>定义了四个宏,声明了四种数据类型,一个标签,多个函数。

...

wint_t

这是一个默认不变的整数类型,参数promotions可以保存任何对应于扩展字符集成员的值,以及至少一个不对应于任何扩展字符集成员的值

WEOF

扩展为 wint_t 类型的常量表达式,其值不对应于扩展字符集的任何成员。(328) 本子条款中的几个函数接受(并返回)它以指示文件结束,也就是说,不再有来自流的输入。它也用作不对应于扩展字符集的任何成员的宽字符值。


  1. 宏 WEOF 的值可能与 EOF 的值不同,不必为负。

EOF 是一个负值,它是getc() 唯一可以返回的负值。我看到它通常定义为(-1),同样WEOF 定义为((wint_t)-1)

是否有任何常见的 C 环境将这些宏中的任何一个定义为不同的东西?

标准委员会保留不同值的可能性的理由是什么,尤其是WEOF 的非负值?

【问题讨论】:

  • 这也很大程度上取决于wint_t 的定义。例如,如果是unsigned shortsizeof(int) > sizeof(unsigned short),则为EOF != WEOF(它与符号扩展有关,或者更确切地说是缺少符号扩展)。
  • 何必呢?使用宏而不是幻数是一种很好的做法,并且无论如何都会使代码更清晰。回覆。 wint:IIRC,Windows 有 16 位 wchar_t,它需要所有 16 位来表示字符。允许 WEOF 的非负值将允许为标记保留单个代码,而不是可用代码空间的一半。
  • 假设,一个实现可能对-1 作为字符代码有一些合法用途,因此可能希望为EOF 选择一个不同的值。

标签: c macros language-lawyer eof


【解决方案1】:

标准委员会保留不同值的可能性的理由是什么,尤其是WEOF 的非负值?

int 类型总是有符号的,负值总是包含在范围内,因此EOF 宏可以被标准定义为-1。

但是wint_t 类型可能是有符号或无符号1,因此标准不能将宏 WEOF 定义为特定值。实现必须选择它,因为实现定义了wint_t 的类型及其符号,它还必须为WEOF 选择一个值。


1(引自:ISO/IEC 9899:201x 7.20.3 其他整数类型的限制 5)
如果wint_t(见7.29)定义为有符号整数类型,WINT_MIN的值不大于-32767,WINT_MAX的值不小于32767;否则,wint_t定义为无符号整数类型,WINT_MIN的值为0,WINT_MAX的值不小于65535。

【讨论】:

  • 我很想阅读建设性的 cmets 以及对正确答案的反对意见。
  • 我没有投反对票,但恕我直言,将wint_t 定义为 unsigned 类型是一种误导:名称另有说明。我认为wint_t 的基本原理是有一个可能更大的类型来处理wchar_t 的所有值和一些指示文件结尾的特殊值。最后,整个宽字符支持一团糟:wchar_t 可以签名,但 L'a' 未签名,char16_tchar32_t 未签名,但 char 可能已签名,@987654341 可能@... 为了解决这个混乱的问题,WEOF 可以是无符号的,与 EOF 不同。
  • @chqrlie 标准的定义是我的错吗?
  • 我并不是说这是你的错,事实上,我赞成你的回答,我只是强调委员会认为适合刻在标准中以反映当时的使用情况的潜在不一致(我想)。一致性要求charwchar_t 都是无符号的,wint_t 的符号范围更大,EOFWEOF 可以是(-1)(wint_t)(-1)
【解决方案2】:

EOF 的值 -1 允许简单有效地实现 ctype 宏(对于小型 char 的常见情况,例如 8 位左右)。典型的实现可能如下所示:

unsigned __ctypes[257] = { 0 /* for EOF */, ... };

#define isalpha(c) (__ctypes[(c)+1] & _ALPHA_BITS)

将 EOF 定义为任何其他整数并没有特别的好处,因此 -1 很可能用于任何具有小 char 类型的合理实现中。

对于较大的wchar_t,表会太大,因此 wctype 函数可能会以不同的方式实现。因此,给予 WEOF 任何特定值(包括 -1)的动机较少。

【讨论】:

  • 这个实现的问题是缺乏对签名字符的支持。尽管如果 char 可能为负,则使用 char 参数调用 isalpha 是不正确的,但这是一个非常常见的错误。 glibc 的实现使用一个包含 384 个条目的数组来处理有符号和无符号字符值。在这样的实现中,将EOF 定义为(-129) 是有意义的。同样,将WEOF 定义为((wint_t)(-1)) 可以避免对错误地在宽流上使用((c = getc(f)) != EOF) 的程序员造成不必要的苛刻。
【解决方案3】:

在Xinu OS EOF is defined as -2。见Actual implementation of EOF different from -1

OTOH wint_t 可以是无符号类型,因此WEOF != -1 的实际实现有很多。例如,在 MSVC 中,wint_tunsigned shortWEOF(wint_t)(0xFFFF)。从技术上讲U+FFFF isn't a valid Unicode character 所以它可以用于WEOF,就像-1sizeof(char) == sizeof(int) 的实现中用于EOF。另请参阅

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-21
    • 1970-01-01
    • 2016-02-18
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    相关资源
    最近更新 更多