c - ASCII、ISO 8859-1、Unicode 在 C 中如何工作?

标签 c terminal utf-8 console-application iso-8859-1

嗯,我真的很怀疑,C如何使用编码,首先我有一个C文件,用ISO 8859-1编码保存,包含test.c内容,运行程序时字符ÿ不是在linux控制台上正确显示,我知道默认情况下它使用utf-8,但是如果utf-8使用与ISO 8859-1相同的256个字符,为什么程序不能正确显示'ÿ'字符?还有一个问题,为什么test2能正确显示‘ÿ’字符?其中 test2.c 文件是 UTF-8 并且 file.txt 也是 UTF-8 ?换句话说,编译器不是会提示宽度是多字符吗?

测试1.c

  // ISO 8859-1
  #include <stdio.h>

  int main(void)
  {
    unsigned char c = 'ÿ';
    putchar(c);
    return 0;
  }

  $ gcc -o test1 test1.c
  $ ./test1
  $ ▒

测试2.c

  // ASCII
  #include <stdio.h>

  int main(void) 
  {

     FILE *fp = fopen("file.txt", "r+");
     int c;

     while((c = fgetc(fp)) != EOF)
        putchar(c);
     return 0;
 }

文件.txt:UTF-8 abcdefÿghi

  $ gcc -o test2 test2.c
  $ ./test2
  $ abcdefÿghi

嗯,就是这样,如果你能帮我提供详细信息,我将非常感激,:)

最佳答案

由于多种原因,字符编码可能会令人困惑。以下是一些解释:

在 ISO 8859-1 编码中,字符 y 带有分音符 ÿ(最初是 ij 的连字) )被编码为0xFF(255)的字节值。 Unicode do 中的前 256 个代码点对应于 ISO 8859-1 中的相同字符,但流行的 Unicode UTF-8 编码对大于 127 的代码点使用 2 个字节,因此 ÿ 在 UTF-8 中编码为 0xC3 0xBF

当您读取文件 file.txt 时,您的程序一次读取一个字节并将其原封不动地输出到控制台(旧系统上的行结尾除外),ÿ 被读取为 2 个单独的字节,逐个输出,并且终端显示 ÿ,因为为终端选择的区域设置也使用 UTF-8 编码。

更令人困惑的是,如果源文件使用 UTF-8 编码,则 "ÿ" 是长度为 2 的字符串,并且 'ÿ' 被解析为多字节字符持续的。多字节字符常量非常困惑且不可移植(该值可以是 0xC3BF 或 0xBFC3,具体取决于系统),强烈建议不要使用它们,并且编译器应配置为在看到它时发出警告(gcc -Wall -韦斯特拉)。

更令人困惑的是:在许多系统上,默认情况下都会对 char 类型进行签名。在本例中,字符常量 'ÿ'(ISO 8859-1 中的单个字节)的值为 -1 且类型为 int ,无论您在源代码中如何编写:'\377''\xff' 也将具有 -1 值。这样做的原因是与 "ÿ"[0] 的值一致,即值为 -1char。这也是宏 EOF 最常见的值。

在所有系统上,getchar() 以及 getc()fgetc() 等类似函数返回 0< 之间的值UCHAR_MAXEOF 的特殊负值,因此来自文件的字节 0xFF,其中字符 ÿ 编码为 ISO 8859- 1 作为值 0xFF255 返回,如果 char 有符号,则该值与 'ÿ' 不同,如果源代码采用 UTF-8 格式,则也与 'ÿ' 不同。

根据经验,不要在字符常量中使用非 ASCII 字符,不要对用于字符串和文件内容的字符编码进行假设,并配置编译器使 char 无符号默认值(-funsigned-char)。

如果您处理外语,强烈建议所有文本内容(包括源代码)使用 UTF-8。请注意,使用此编码将非 ASCII 字符编码为多个字节。研究UTF-8 encoding ,它非常简单和优雅,并使用库来处理文本转换,例如大写。

关于c - ASCII、ISO 8859-1、Unicode 在 C 中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71362599/

相关文章:

Cygwin/Cygserver 共享内存

c - 指向数组的指针

python - 修复python多处理中多个进度条(tqdm)的跳转

linux - if语句语法错误

c - 如何纠正旧 GNU/Linux 机器上的整数溢出行为?

C、使用字符串

macos - 如何让终端程序支持光标键?

mysql - 如何将 Teradata 表转换为 utf8

arrays - SWIFT 解析问题

encoding - liquibase 破坏 UTF-8 变更集