首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C编程:如何为Unicode编程?

C编程:如何为Unicode编程?
EN

Stack Overflow用户
提问于 2009-02-08 21:22:16
回答 8查看 53.9K关注 0票数 86

进行严格的Unicode编程需要哪些前提条件?

这是否意味着我的代码不应该在任何地方使用char类型,并且需要使用可以处理wint_twchar_t的函数

多字节字符序列在此场景中扮演的角色是什么?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2009-02-08 22:44:07

请注意,这本身并不是关于“严格的unicode编程”,而是一些实际经验。

我们公司所做的就是围绕IBM的ICU库创建一个包装器库。包装库具有UTF-8接口,并在需要调用ICU时转换为UTF-16。在我们的例子中,我们并不太担心性能问题。当性能是一个问题时,我们还提供了UTF-16接口(使用我们自己的数据类型)。

应用程序可以在很大程度上保持原样(使用char),尽管在某些情况下,它们需要了解某些问题。例如,代替strncpy(),我们使用了一个包装器来避免截断UTF-8序列。在我们的例子中,这已经足够了,但也可以考虑检查组合字符。我们还提供了用于计算码点数量、字素数量等的包装器。

在与其他系统交互时,我们有时需要进行自定义字符组合,因此您可能需要一些灵活性(取决于您的应用程序)。

我们不使用wchar_t。使用ICU可以避免在可移植性方面出现意想不到的问题(当然,不会出现其他意想不到的问题:-)。

票数 22
EN

Stack Overflow用户

发布于 2009-02-09 07:00:50

C99或更早版本

C标准(C99)提供了宽字符和多字节字符,但是由于不能保证这些宽字符可以容纳的内容,它们的值在某种程度上是有限的。对于给定的实现,它们提供了有用的支持,但如果您的代码必须能够在实现之间移动,则不能充分保证它们将是有用的。

因此,Hans van Eck建议的方法(即为Unicode库编写ICU - International组件的包装器)是合理的。

UTF-8编码有很多优点,其中之一是,如果您不去处理数据(例如,通过截断它),那么它可以被不完全了解UTF-8编码复杂性的函数复制。这绝对不是wchar_t的情况。

完整的Unicode是一种21位格式。也就是说,Unicode保留了从U+0000到U+10FFFF的代码点。

UTF-8、UTF-16和UTF-32格式(其中UTF代表Unicode转换格式-参见Unicode)的一个有用之处在于,您可以在这三种表示之间进行转换,而不会丢失信息。每一个都可以代表其他人可以代表的任何东西。UTF-8和UTF-16都是多字节格式。

众所周知,UTF-8是一种多字节格式,具有精心的结构,可以可靠地找到字符串中字符的开头,从字符串中的任何位置开始。单字节字符的高位设置为零。多字节字符的第一个字符以位模式110、1110或11110之一开始(对于2字节、3字节或4字节字符),后续字节始终以10开始。连续字符始终在0x80范围内。0xBF。有一些规则要求UTF-8字符必须以最小可能的格式表示。这些规则的一个后果是字节0xC0和0xC1 (也就是0xF5..0xFF)不能出现在有效的UTF-8数据中。

代码语言:javascript
运行
复制
 U+0000 ..   U+007F  1 byte   0xxx xxxx
 U+0080 ..   U+07FF  2 bytes  110x xxxx   10xx xxxx
 U+0800 ..   U+FFFF  3 bytes  1110 xxxx   10xx xxxx   10xx xxxx
U+10000 .. U+10FFFF  4 bytes  1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx

最初,人们希望Unicode是一个16位的代码集,所有的东西都可以放在一个16位的代码空间中。不幸的是,现实世界更加复杂,它必须扩展到目前的21位编码。

因此,UTF-16是用于“基本多语言平面”的单个单元(16位字)代码集,这意味着具有Unicode代码点U+0000的字符。U+FFFF,但对此范围之外的字符使用两个单位(32位)。因此,使用UTF-16编码的代码必须能够处理可变宽度编码,就像UTF-8一样。双单位字符的代码称为代理。

代理是来自两个特殊范围的Unicode值的代码点,保留用作UTF16中成对代码单元的前导值和拖尾值。领先的,也称为高,代理人是从U+D800到U+DBFF,和尾随,或低,代理人是从U+DC00到U+DFFF。它们被称为代理,因为它们不直接表示字符,而只是作为一对字符。

当然,UTF-32可以在单个存储单元中对任何Unicode代码点进行编码。它对于计算是有效的,但对于存储是无效的。

你可以在ICU和Unicode网站上找到更多的信息。

C11和<uchar.h>

C11标准改变了规则,但直到现在(2017年中),并不是所有的实现都跟上了这些变化。C11标准将Unicode支持的更改总结为:

  • Unicode字符和字符串(<uchar.h>) (最初在ISO/IEC TR 19769:2004中指定)

下面是对该功能的一个简单概述。该规范包括:

6.4.3通用字符名称

语法

通用字符名称:

\u十六进制四边形

\U十六进制-四进制

十六进制四元组:

十六进制数字十六进制数字十六进制数字

7.28 Unicode实用程序<uchar.h>

<uchar.h>声明了用于操作Unicode字符的类型和函数。

声明的类型是mbstate_t (在7.29.1中描述)和size_t (在7.19中描述);

char16_t

它是用于16位字符的无符号整数类型,与uint_least16_t相同(在7.20.1.2中描述);以及

char32_t

它是用于32位字符的无符号整数类型,与uint_least32_t相同(也在7.20.1.2中描述)。

(翻译交叉引用:<stddef.h>定义size_t<wchar.h>定义mbstate_t<stdint.h>定义uint_least16_tuint_least32_t。)<uchar.h>头还定义了一组最小的(可重新启动的)转换函数:

  • mbrtoc16()
  • c16rtomb()
  • mbrtoc32()
  • c32rtomb()

在使用\unnnn\U00nnnnnn表示法的标识符中可以使用哪些Unicode字符是有规则的。您可能必须主动激活对标识符中此类字符的支持。例如,GCC要求-fextended-identifiers在标识符中允许这些。

请注意,仅举一个平台的例子,macOS that (10.12.5)不支持<uchar.h>

票数 43
EN

Stack Overflow用户

发布于 2009-02-09 16:34:14

这个FAQ包含了丰富的信息。在该页面和this article by Joel Spolsky之间,您将有一个良好的开端。

一路走来,我得出了一个结论:

  • wchar_t在Windows上是16位的,但在其他平台上不一定是16位。我认为这在Windows上是必要的,但在其他地方可能可以避免。它在Windows上很重要的原因是,您需要它来使用名称中包含非ASCII码的文件(以及W版本的functions).
  • Note,接受wchar_t字符串的Windows需要使用UTF16编码。另请注意,这与UCS-2不同。注意代理项对。这个test page有启发性的测试。
  • 如果你在Windows上编程,你不能使用fopen()fread()fwrite()等,因为它们只接受char *,不理解UTF-8编码。让可移植性变得痛苦。
票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/526430

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档