如果输入是isspace()
或等于representable as unsigned char
,则EOF
有效。
getchar()
从stdin读取下一个字符。
当getchar()!=EOF
;所有getchar()
返回值可以表示为unsigned char
?
uintmax_t count_space = 0;
for (int c; (c = getchar()) != EOF; )
if (isspace(c))
++count_space;
愿这段代码导致未定义的行为吗?
根据C11 WG14 draft version N1570:
§7.21.7.6/ 2
getchar
函数等效于带有参数stdin的getc
。§7.21.7.5/ 2
getc
函数相当于fgetc
...§7.21.7.1/ 2 [
!=EOF
案例] ......fgetc
函数获得该字符作为unsigned char
转换为int
... [...]中的文本是我的。
即,
isspace()
接受getchar()
值getchar()!=EOF
值都可以表示为unsigned char
如果你认为它太明显了(“它还能做什么”),那就再想一想。例如,在the related case中:isspace(CHAR_MIN)
可能未定义,即,将字符传递给字符分类函数可能是未定义的行为!
如果UCHAR_MAX > INT_MAX
结果可能是实现定义的:
§6.3.1.3/ 3否则,新类型已签名,其值无法表示;结果是实现定义的,或者引发实现定义的信号。
getchar()
的返回值与fgetc()
的格式相同。 C11定义了fgetc()
中7.21.7.1p2-3的返回值:
- 如果没有设置stream指向的输入流的文件结束指示符并且存在下一个字符,则
fgetc
函数将该字符作为unsigned char
转换为int
并推进该流的相关文件位置指示符(如果定义)。返回
- 如果设置了流的文件结束指示符,或者流位于文件结尾,则设置流的文件结束指示符,并且
fgetc
函数返回EOF
。否则,fgetc
函数返回stream指向的输入流中的下一个字符。如果发生读取错误,则设置流的错误指示符,并且fgetc
函数返回EOF
。 [289]
由于这是一个unsigned char
转换为int
,int
几乎总是与unsigned char具有相同的值。
在某些sizeof(int) == 1
平台上的高值可能不是这样;然而,这些主要是DSP平台,因此几乎可以肯定在这些平台上不需要进行字符分类。
is*
函数经过精心定义,因此可以直接使用*getc*
C11 7.4p1的返回值:
1标题
<ctype.h>
声明了几个对字符分类和映射有用的函数。 [198]在所有情况下,论证都是int
,其值应表示为unsigned char
或等于宏EOF
的值。如果参数具有任何其他值,则行为未定义。
即将EOF
传递给is*
函数是合法的。当然isanything(EOF)
将始终返回0,因此要计算连续的空白字符,可以使用以下内容:
while (isspace(getchar())) space_count ++;
但是,有符号的char值不正常,例如,如果将EOF
以外的负值传递给任何字符分类函数,则已知MSVC C调试库将中止。