【问题标题】:Dealing with char values over 127 in C在 C 中处理超过 127 的字符值
【发布时间】:2016-02-04 19:16:26
【问题描述】:

我是 C 编程的新手,我在尝试在 char 数组中分配超过 127 (0x7F) 的值时遇到了一些问题。在我的程序中,我使用通用二进制数据,将先前获取的字节流(例如,使用 fopen 或 fgets,然后使用一些按位运算处理)打印为 %c 或 %d 没有任何问题。
但如果我尝试从它的数值中打印一个字符,如下所示:

printf("%c\n", 128);

它只打印 FFFD(替换字符)。
这是另一个示例:

char abc[] = {126, 128, '\0'}; // Manually assigning values
printf("%c", abc[0]); // Prints "~", as expected
printf("%c", 121); // Prints "y"
pritf("%c", abc[1]; // Should print "€", I think, but I get "�"

我有点困惑,因为我可以通过这些方式打印低于 128 的每个字符。
我问这个的原因是因为我需要使用 rand( ) 函数。
这是一个例子:

char abc[10];
srand(time(NULL));
abc[0] = rand() % 256; // Gives something between 00:FF ...
printf("%c", abc[0]); // ... but I get "�"

如果这有帮助,源代码以 UTF-8 编码,但更改编码没有任何效果。

【问题讨论】:

  • 我不明白你的意思 printf("%c\n", 128); 只是返回 FFFD(替换字符)。 函数 printf 返回打印的字符数。
  • @WeatherVane 对不起,我的意思是它在屏幕上打印替换字符,而不是作为返回值。已编辑
  • 程序之外的其他东西必须生成那个“替换字符”。当我运行你的程序时,它会打印一个值为0x80的字符。

标签: c character-encoding char


【解决方案1】:

在 C 中,charunsigned charsigned char 是不同的类型。它的范围为CHAR_MINCHAR_MAX。然而,它与unsigned char/signed char 之一具有相同的范围。通常这些是 8 位类型,但可能更多。见CHAR_BIT。所以典型的范围是[0 to 255][-128 to 127]

如果char 没有签名,abc[1] = 128 就可以了。如果 char 已签名,则 abc[1] = 128 是实现定义的(见下文)。典型的 I-D 是abc[1],其值为-128

printf("%c\n", 128); 会将 int 值 128 发送到 printf()"%c" 将该值转换为 unsigned char。到目前为止没有问题。输出上出现的内容取决于输出设备如何处理代码 128。也许是 Ç,也许是别的东西。

printf("%c", abc[1]; 将发送 128 或者是 I-D。如果发送了 I-D 和 -128,则将 -128 转换为 unsigned char 是 128,然后再次打印 128 的代码。

如果输出设备需要 UTF8 序列,则以代码 128 开头的 UTF8 序列是无效的(它是一个意外的继续字节),许多此类系统将打印替换字符,即 unicode FFFD。


signed char 范围之外的值转换为 char 调用:

新类型是有符号的,值不能在其中表示;无论是 结果是实现定义的或引发了实现定义的信号。 C11dr §6.3.1.3 3

【讨论】:

  • 谢谢。原来终端正在打印FFFD,因为它是无效的UTF-8,同时强制输出例如ISO-8859-1 给出了预期的结果,就像@KeithThompson 猜测的那样。除此之外,我完全不知道 signed char 的 UB 大于 127,因为我的系统显然将 char 转换为正确的类型,但这不是我应该依赖的东西。
  • 我认为这是“实现定义的行为”而不是“未定义的行为”。 CISO/IEC9899:201x 6.3.1.3.3:“否则,新类型是有符号的,并且值不能在其中表示;结果要么是实现定义的,要么是产生实现定义的信号。”
  • @Adrian McCarthy 同意。答案已修改。
  • pritf("%c", abc[1]; - pritf 附近打印错误
  • @SetiVolkylany 已编辑
【解决方案2】:

首先,让我告诉你,char 的签名是由实现定义的。

如果您必须处理超过 127 的 char 值,您可以使用 unsigned char。它可以处理0-255。

此外,您应该使用%hhu 格式说明符来打印unsigned char 的值。

【讨论】:

    【解决方案3】:

    如果您正在处理字节,请使用 unsigned char 而不是 char 作为您的数据类型。

    关于打印,您可以以十六进制而不是十进制或字符形式打印字节:

    printf("%02X", abc[0]);
    

    您可能不想将这些字节打印为字符,因为您很可能会处理 UTF-8 字符编码,而这似乎不是您想要的。

    【讨论】:

      猜你喜欢
      • 2020-12-06
      • 2014-06-20
      • 1970-01-01
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 2016-12-03
      • 2010-10-25
      • 1970-01-01
      相关资源
      最近更新 更多