c - char如何存储两个数字?

标签 c char cyrillic

下一个案例:我有西里尔字母“б”。运行下一个代码:

int main() {
    char c;
    scanf("%c", &c);
    printf("%d\n", c);
    return 0;
}

显示 -48。但是当我调试这个变量 c 时,它会显示下一个:-48 '\320' enter image description here .

那么这是如何工作的呢?这是一个指向 2 长度数组的指针吗?或者它如何能够存储两个数字?

最佳答案

一个 char 变量可以用来存储一个小的1 整数,或者一个字符(更准确地说,代码单元)在一些不太明确的地方,一般是基于ASCII的编码。这里调试器只是试图通过显示 c 内容的两个(有争议的)有意义的表示来提供帮助。


让我们想象一下,您实际上编写了 a 而不是 б;在这种情况下,调试器会写类似

c = {char} 97 'a'

因为c中实际存储的数字是97,解码为ASCII,对应字母a

不幸的是,您可以将所有可能的字符放入单个 8 位 char 值中的想法是完全有缺陷的,因此当今使用最广泛的编码 (UTF-8) 恰好是在您的机器上使用的那个,需要多个代码单元(≈字节)来表示单个代码点(≈逻辑字符)(更多细节in this question)。特别地,б 表示为一个两个 字节的字符串,即字节 0xD0 和 0xB1。

C 对 UTF-8 或代码点一无所知;如果您将 %c 指定为 scanf,它会读取单个字节,而不管它是否足以表示完整的 UTF-8 代码点这一事实。因此,只有第一个字节被读取,c 只包含 0xD0 值; 0xB1 仍在缓冲区中,尚未读取。

回到调试器显示的值,首先必须注意,在您的平台上(不幸的是,在许多平台上),char 是有符号的。因此,0xD0 字节被解释为带符号的值 -48(实际上,0xD0 = 208,它在 127 处“环绕”;208 - 256 = -48)。

至于'\320':此处的调试器希望显示该值的ASCII 表示;然而,字节 0xD0 超出了 ASCII 字符范围2,所以这里它以转义序列显示。您可能熟悉 '\n' 表示换行符或 \0 表示 NUL 字符;一般情况下,\后接一到三位数字在C语言中表示对应八进制值的字节; 0320 确实是八进制的 208,也就是十进制的 0xD0。

所以,这里没有什么神秘之处:c 仍然包含一个值(它只是你角色的“一半”);您所看到的只是其内容的两个(同样不方便)表示。


注释

  1. 在大多数平台上,[-128, 127] 或 [0, 255],具体取决于 char 的符号(不幸的是,这是实现定义的)。
  2. 的确,UTF-8 扩展 ASCII 仅使用设置了高位(ASCII 未使用)的字节作为其多字节序列;这确保它们不会被误解为 ASCII 文本。

关于c - char如何存储两个数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53642076/

相关文章:

c++ - 显示从索引 i 到字符串末尾的 std::string

matlab, utf-8, 西里尔文

c++ - 如何将整数转换为其等效的 ascii

c++ - 在 sfml 中使用 UTF8

java - 无法使用 WorkBook Factory 打开西里尔文密码保护的 xlsx 文件

c - Valgrind 错误根据输入而变化。如何解决?

c - 如何在 mingw-w64 gcc 7.1 中打印 size_t 而不发出警告?

c - 如果函数声明不在头文件中,是否需要 static 关键字?

c++ - 默认情况下全局变量是extern还是相当于在全局中用extern声明变量?

java - 对非字母字符使用 Arrays.sort() ,例如 {'+' '1' 'D' }