程序究竟如何在内部将所有内容转换为UTF-8?

dla*_*tte 3 c internationalization

  • 它使用setlocale()吗?
  • 对于UTF-8语言环境中的所有输入字符串,它是否假设utf-8?
  • 我理解unicode是什么以及它与utf-8有什么关系,但是如何在内部用它们的所有字符串"转换为它"呢?

它如何将所有输入字符串转换为UTF-8?它是否使用C库函数?

当前工作区域设置是否必须是UTF-8语言环境?

更新:如果具体的技术细节可以在你的答案中,那将是伟大的,因为这更符合我正在寻找的.我已经理解了在内部使用UTF-8的原因以及为什么它使得处理多个语言环境变得更加简单.

更新:提到简单地使用iconv和/或ICU的答案,但是,如何strcmp()与其他所有例程一起知道将它们作为UTF-8进行比较呢?是否setlocale()必须运行?或者没关系?

bma*_*ies 5

由于有许多假设在起作用,因此有点难以分辨从哪里开始.

在C中我们知道并喜欢它,有一个'char'数据类型.在所有常用的实现中,该数据类型包含一个8位字节.

在语言中,与您使用的任何库函数相反,这些东西只是二进制补码整数.它们没有任何"特征"语义.

一旦从标准库中调用函数,其名称中包含'str'或'is'(例如strcmp,isalnum),就会处理字符语义.

C程序需要在Unicode发明之前应对由字符语义构成的巨大混乱.各种组织发明了大量的编码标准.有些是每个字节一个字符.有些是每个字节多个字符.在某些情况下,提问总是安全的if (charvalue == 'a').在其他情况下,由于多字节序列,可能会得到错误的答案.

几乎在每个现代环境中,标准库的语义都由语言环境设置决定.

UTF-8在哪里?很久以前,Unicode联盟的成立是为了试图摆脱所有这些混乱的秩序.Unicode为许多很多字符定义了一个字符值(在32位字符空间中).目的是涵盖实际使用的所有特征.

如果您希望您的代码使用英语,阿拉伯语,中文和Sumerian Cuneiform,您需要Unicode字符语义,而不是编写躲避和编织不同字符编码的代码.

从概念上讲,最简单的方法是使用32位字符(UTF-32),因此每个逻辑字符只有一个项目.大多数人认为这是不切实际的.请注意,在现代版本的gcc中,数据类型wchar_t是32位字符---但Microsoft Visual Studio不同意,将数据类型定义为16位值(UTF-16或UCS-2,具体取决于你的观点).

大多数非Windows C程序都过于投入8位字符进行更改.因此,Unicode标准包括UTF-8,Unicode文本的表示形式为8位字节序列.在UTF-8中,每个逻辑字符的长度在1到4个字节之间.基本的ISO-646('ascii')字符'自己播放',因此对简单字符的简单操作按预期工作.

如果您的环境包含UTF-8的语言环境,那么您可以将语言环境设置为UTF-8语言环境,并且所有标准的lib函数都可以正常工作.如果您的环境不包含UTF-8的区域设置,则需要一个附加组件,如ICU或ICONV.

到目前为止,整个讨论一直停留在内存中的变量数据中.你还必须处理阅读和写作.如果你打电话open(2)或Windows道德等效,你将从文件中获取原始字节.如果那些不是UTF-8,如果你想使用UTF-8,你必须转换它们.

如果你打电话fopen(3),那么标准库可能会试着帮你一个忙,并在它对文件的默认编码的想法和你想要的内存的想法之间进行转换.例如,如果你需要在希腊语语言环境中运行程序并在Big5中读取中文文件,你需要小心你传递给fopen的选项,或者你可能想要躲开它.而且你需要ICONV或ICU来转换UTF-8和从UTF-8转换.

你的问题提到'输入字符串'.这可能是一些事情.在UTF-8语言环境中,argv将是UTF-8.文件描述符0将是UTF-8.如果shell没有以UTF-8语言环境运行,并且您调用setlocaleUTF-8语言环境,则不一定会获得UTF-8中的值argv.如果将文件的内容连接到文件描述符,您将获得文件中的任何内容,无论它恰好处于何种编码状态.

  • Unicode目前定义为使用高达0x10FFFF的值; 转换为UTF-8中最多4个字节.UTF-8能够表示从0到0xFFFFFF的代码点,但最多可以包含6个字节 - 它只是不需要,至少现在是这样. (2认同)