我知道下面的代码被破坏了——getchar()
返回一个int
不是char
——
好的!
char single_byte = getchar();
这是有问题的不止一种方式。
我会假设CHAR_BIT == 8
和EOF == -1
。(我们知道EOF
负数和类型int
;-1
是一个典型的值——事实上我从来没有听说过它有任何其他值。)
Plainchar
可以是签名的或未签名的。
如果它是无符号的,则 的值single_byte
将是刚刚读取的字符的值(表示为 anunsigned char
并简单地转换为 plain char
),或者转换EOF
为char
. 通常EOF
为 -1,转换结果将为CHAR_MAX
, 或 255。您将无法区分EOF
255 和实际输入值 - 因为/dev/urandom
以相等的概率返回所有字节值(并且永远不会干涸) ,你0xff
迟早会看到一个字节。
但这不会终止您的输入循环。你的比较(single_byte == EOF)
永远不会是真的;因为single_byte
在这种情况下是无符号类型,所以它永远不能等于EOF
. 即使从有限文件而不是从无限设备(如/dev/urandom
. (您可以编写(single_byte == (char)EOF)
,但当然这不能解决根本问题。)
由于您的循环确实终止了,我们可以得出结论,plainchar
在您的系统上已签名。
如果plainchar
被签名,事情会稍微复杂一些。如果您读取 0..127 范围内的字符,则其值将存储在single_byte
. 如果您读取 128..255 范围内的字符,则该int
值将转换为char
; 因为char
是有符号的并且值超出范围,所以转换的结果是实现定义的。对于大多数实现,该转换会将 128 映射到 -128、129 到 -127、... 255 到 -1。如果getchar()
返回EOF
(通常)为-1,则转换定义明确并产生-1。同样,您无法区分EOF
和 输入字符与 value -1
。
(实际上,从 C99 开始,转换也可以引发实现定义的信号。幸运的是,据我所知,实际上没有实现这样做。)
if (single_byte == EOF)
printf("EOF is implemented in terms of 0x%x.\n", single_byte);
getchar()
同样,如果实际返回EOF
或者您只是读取具有 value 的字符,则此条件将为真0xff
。该%x
格式需要一个类型为 的参数unsigned int
。single_byte
是类型char
,几乎肯定会被提升为int
. 现在,如果值在两种类型的可表示范围内,您可以int
使用unsigned int
格式打印值。但由于' 的值是(它只是比较等于),它不在那个范围内。, 使用格式,假设参数是类型的(这不是转换)。并且是采用 32 位值的可能结果single_byte
-1
EOF
printf
"%x"
unsigned int
0xffffffff
int
-1
并假设它真的是一个unsigned int
.
我只想指出,将 的结果存储getchar()
在一个int
对象中要比分析将其存储在char
.