C 如何区分字节长字符和 2 字节长字符?

Posted

技术标签:

【中文标题】C 如何区分字节长字符和 2 字节长字符?【英文标题】:How does C distinguish between a byte long character and a 2 byte long character? 【发布时间】:2015-08-03 11:06:46 【问题描述】:

我有这个示例代码:

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(void)
    printf("%li\n",sizeof(char));
    char mytext[20];
    read(1,mytext,3);
    printf("%s",mytext);
    return 0;

第一次运行:

koray@koray-VirtualBox:~$ ./a.out 
1
pp
pp
koray@koray-VirtualBox:~$ 

好吧,我认为这一切都是意料之中的,因为 p 是 ASCII 中定义的 1 字节长的字符,而我正在读取 3 个字节。 (2 个 p 和换行符)在终端中,我再次看到 2 个字符。

现在让我们尝试使用 2 个字节长的字符:

koray@koray-VirtualBox:~$ ./a.out 
1
ğ
ğ

我不明白的是,当我将字符“ğ”发送到 mytext 变量指向的内存时,16 位被写入该区域。由于 'ğ' 在 utf-8 中是 11000100:10011110,因此这些字节被写入。

我的问题是,当打印回标准输出时,C(或者我应该说内核?)如何知道它应该读取 2 个字节并解释为 1 个字符而不是 2 个 1 字节字符?

【问题讨论】:

@DavidSchwartz 这对我有什么帮助? 确实没有。 UTF-8 平台倾向于实现w_char C 中使用了两组不同的函数(用于 printf 等函数),一组用于 ASCII,另一组用于 UNICODE。 Microsoft 有一个使用 的扩展,其中程序可以使用相同的名称,例如 TCHAR 代替 char (ASCII) 或 WCHAR / wchar_t / unsigned short (UNICODE)、_tprintf()、_T("...")对于字符串文字, ... ,根据项目设置是 ASCII 或 UNICODE。 【参考方案1】:

C 不解释它。您的程序读取 2 个字节并输出相同的 2 个字节,而不关心它们是什么字符(或其他任何字符)。

您的终端对您的输入进行编码,并将您的输出重新解释为相同的两字节字符。

【讨论】:

如果我有一个哑终端,它可以将其解释为 2 个 8 位字符? 但是终端怎么知道那是一个2字节的字符呢? 它查看第一位。由于它设置为 1,终端(或任何正在读取字符串的)知道它不是 ascii,并且它包含 2 个字节或更多。它会通过其他位的内容知道它是否更多。 语言环境,终端配置,猜测。想想当你在你的应用程序中硬编码输出而不进一步处理这些字节时会发生什么。例如。您可以使用 Konsole 的配置文件编码设置来显示各种字符/垃圾重复运行那个简单的应用程序,通过不同地解释输出。【参考方案2】:

Ascii 范围从 0 到 127。Unicode 的前 128 个字符是 ascii 字符。

第一位将告诉您您的角色是否在 0-127 范围内或以上。如果为 1,则表示它是 unicode,将考虑 16 位(甚至更多)。

这个问题与:What's the difference between ASCII and Unicode?密切相关

【讨论】:

你也可以看看***.com/questions/700187/… 哪个进程正在查看第一位以确定范围?重击?如果我将标准输出重定向到具有 > somefile.txt 的文件怎么办 无论是什么渲染字符串都必须做这个检查。在你的情况下,那是终端。 我明白了,所以如果我将字节写入文本文件,打开它的任何进程都需要检查它? 当然。此外,unicode 并不总是 2 个字节。任何解码它都需要不断检查每个字符。

以上是关于C 如何区分字节长字符和 2 字节长字符?的主要内容,如果未能解决你的问题,请参考以下文章

Python - 如何创建一个 8 字节长的随机字符串? [复制]

UTF-8 中的所有汉字字符都是 3 个字节长吗?

int,long,float的区别是啥?

长字符串原始字符串和字节

c语言的基本整型(int)和短整型(short)又啥不一样?这些有啥用?

请问C语言中float,long,int等是怎么区分范围的