Joh*_*ger 7 c io portability type-conversion
也许我正在过度思考这个问题,因为它似乎应该更加容易.我想获取int类型的值,例如fgetc()返回的值,如果它不是文件结束代码,则将其记录在char缓冲区中.例如:
char buf;
int c = fgetc(stdin);
if (c < 0) {
/* handle end-of-file */
} else {
buf = (char) c; /* not quite right */
}
Run Code Online (Sandbox Code Playgroud)
但是,如果平台已经签署了默认字符,那么fgetc()返回的值可能超出了char的范围,在这种情况下,将其转换或赋值给(signed)char会产生实现定义的行为(对吗?).当然,那里有大量的代码完全相当于这个例子.是否完全依赖于实现定义的行为和/或假设7位数据?
在我看来,如果我想确定我的代码的行为是由C定义为我想要的,那么我需要做这样的事情:
buf = (char) ((c > CHAR_MAX) ? (c - (UCHAR_MAX + 1)) : c);
Run Code Online (Sandbox Code Playgroud)
我认为无论是默认字符是有符号还是无符号,无论字符大小如何,都会产生定义的,正确的行为.是对的吗?这样做是否真的需要确保可移植性?
fgetc()返回unsigned char和 EOF。EOF 始终 < 0。如果系统的char是signed或unsigned,则没有区别。
C11dr 7.21.7.1 2
如果流指向的输入流的文件结束指示符未设置并且存在下一个字符,则 fgetc 函数会获取该字符作为转换为 int的无符号字符,并推进流的关联文件位置指示符(如果已定义)。
我担心的是,它看起来依赖于 2 的补语,并且意味着unsigned char和 的范围char都一样宽。今天,这两个假设几乎总是正确的。
buf = (char) ((c > CHAR_MAX) ? (c - (UCHAR_MAX + 1)) : c);
[根据OP评论编辑]
让我们假设在tofgetc()范围内返回的字符与 stuff-able 不同,然后用 替换会更便携。我们不知道是什么时候进入射程的。CHAR_MINCHAR_MAX(c - (UCHAR_MAX + 1))(c - CHAR_MAX + CHAR_MIN)(c - (UCHAR_MAX + 1))c is CHAR_MAX + 1
可能存在一个signed char范围为 -127 到 +127 和unsigned char范围为 0 到 255 的系统。(5.2.4.2.1),但是当fgetc()获取一个字符时,它似乎已经将unsigned char 自己限制在较小的signed char范围内。 ,然后转换unsigned char为该值并将其返回给用户。OTOH,如果fgetc()返回 256 个不同的字符,无论公式如何,转换为窄范围signed char都将不可移植。