【问题标题】:C: char vs. unsigned char for non-ASCII text dataC:用于非 ASCII 文本数据的 char 与 unsigned char
【发布时间】:2014-12-19 21:17:55
【问题描述】:

这个问题:

What is an unsigned char?

在讨论 C 中的 charunsigned charsigned char 方面做得很好。

但是,它并没有直接说明应该用于非 ASCII 文本的内容。因此,如果我有一个字节数组表示任意字符集中的文本,如 UTF-8 或 Big5(有时是 ASCII),我应该使用 char 还是 unsigned char em>?

我倾向于使用 char,因为否则当数组是 ASCII 并且我使用 strlen 时,gcc 会给我关于指针符号的警告。但我想知道什么是正确的。

【问题讨论】:

  • 是的,在这方面接受的答案是正确的。 C 字符串类型是由 NUL 字节终止的非 NUL 字节序列,未指定编码,但如果您有任何选择,请使用 UTF-8。
  • 除了 UTF-8,你不想使用 strlen,因为可能有内部 NUL。无论如何,这是一个很大的话题。对于 Unicode,我建议 site.icu-project.org
  • @Deduplicator 请仔细阅读:除了 UTF-8,...可以有内部NUL。我的意思是 OP 所指的:Big5 等。当然 UTF-16 和 UTF-32 也可以包含内部 NUL,所以是的,我写的内容适用于它们 to
  • @JimBalter:你知道带有内部NULs 的 8 位编码不是终结符吗?
  • unsigned char 优于 char(当 char 被签名时)的优势在于 is...() 函数是 signed char 的 UB,因为他们期望 unsigned char 或 EOF。

标签: c string unsigned-char


【解决方案1】:

您提出的问题可能比您预期的要广泛得多。

为了直接回答这个问题,大多数实现都使用“字节”作为底层缓冲区。在这方面标准uint8_t typedef 是你最好的选择。这主要是因为大多数字符集使用可变数量的字节来存储字符,因此在编码和解码过程中单独的字节处理是必不可少的。它还简化了不同“字节序”之间的转换。

通常,在 ASCII 编码或其他单字节代码页(0-255 范围)之外的任何内容上使用 strlen 是不正确的。在 Big5、UTF-8/16 或 Shift-JIS 等任何多字节编码上肯定是不正确的。

【讨论】:

  • strlen() 在 UTF-8 与 ASCII 上的安全性如何?两者都有代码 0。C simple 使用代码 0 (ASCII NUL) 作为终止字符,因此不允许使用 ASCII NUL 字符的 C 字符串。代码同样可以使用 Unicode 0(以 UTF-8 编码为单个 0 字节)作为终止字符。并不是说我喜欢使用 0 终止的字符串,但是在类似字符串的 UTF-8 编码的 Unicode 字符组上使用 strlen() 并没有看到很大的问题。
  • @chux UTF-8 不是单字节字符编码。它将报告不正确的字符数。也许“安全”不是一个最好的词。
  • 确实 strlen() 不会报告 Unicode 字符的数量,但会安全地报告在 UTF-8 编码中使用的 char 的正确数量(假设 0 终止)。
  • @chux 你是对的。我的主要观点是,在 mbcs 上使用 strlen 通常是个坏主意。通常我们期望strlen 返回字符数,而不是使用的字节数。
  • 这里最好谈谈strcpy,它可以用于多字节编码,只要它们不能有内部'\0'。跨度>
【解决方案2】:

使用普通字符来表示字符。当您想要一个涵盖来自 -127 to +127 的值的有符号整数类型时,请使用有符号字符。使用 unsigned char 具有值范围为 0 to 255 的无符号整数类型。

【讨论】:

  • 技术上 uint8_t 应该用于后者(如果您使用的平台不支持 8 位字符,则会出现编译器错误)
  • 这并没有比 OP 提供的链接多(而且少得多)。即,它不是对所提问题的回答,甚至不反映存在这样的问题。它得到了两个赞成票,真是太棒了。
猜你喜欢
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 2011-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多