感谢那些做出回应的人,并且现在已经阅读了 C99 标准的相关部分,我已经同意一个有点令人惊讶的结论,即存储fgetc()as 类型返回的任意非 EOF 值char而不损失保真度并不能保证是可能的. 在很大程度上,这是由于char无法表示与 一样多的不同值的可能性unsigned char。
就他们而言,stdio 函数保证如果数据被写入(二进制)流并随后读回,那么读回的数据将与原始数据进行比较。事实证明,它的含义比我最初想象的要窄得多,但这确实意味着fputs()必须为它成功输出的每个不同输出一个不同的值char,并且无论转换fgets()适用于将输入字节存储为类型,都char必须准确地反转转换,如果有的话,由此fputs()将产生输入字节作为其输出。然而,据我所知,fputs()并且fgets()允许在他们不喜欢的任何输入上失败,因此不确定 fputs() 是否将每个可能的char值映射到unsigned char.
此外,虽然fputs()和fgets()就像分别执行fputc()和fgetc()调用的序列一样操作,但没有指定它们可能char在内存中的unsigned char值和流上的基础值之间执行什么转换。 但是,如果平台fputs()为此目的使用标准整数转换,那么正确的反向转换就是我建议的:
int c = fgetc(stream);
char buf;
if (c >= 0) buf = (char) ((c > CHAR_MAX) ? (c - (UCHAR_MAX + 1)) : c);
这直接来自整数转换规则,该规则指定通过添加或减去 <target type>_MAX + 1 的整数倍数将整数值转换为无符号类型,以将结果带入目标类型的范围,由整数类型表示的约束。它为此目的的正确性不取决于char值的特定表示或是否char被视为有符号或无符号。
但是,如果 char不能表示与 一样多的不同值unsigned char,或者如果存在拒绝输出的char值fgets()(例如负值),则可能存在一开始就不可能由转换c产生的值。char没有反向转换参数适用于这些字节,甚至可能没有有意义的char值对应于它们。在任何情况下,给定的转换是否是写入数据的正确反向转换fputs()似乎是实现定义的。是否buf = (char) c会产生相同的效果当然是由实现定义的,尽管它确实在很多系统上都有。
总的来说,我对实现定义了多少 CI/O 行为细节感到震惊。这让我大开眼界。