3

我有与 Unicode 相关的问题,在const char*.

  1. 据我了解,utf-8 包含 2、3 或 4 字节字符,范围从磅符号到汉字字符。在字符串中,这些以十六进制值表示,使用 \u 作为转义序列。我也明白,在字符串中使用十六进制转义时,将包含其值可以包含在转义中的字符。例如说“abc\x0f0dab”将包含 0f0dab 以在 \x 中被视为十六进制,即使您只想考虑 0f0d。

现在在编写 Unicode 字符串时,假设您要编写“abcdef₤ghi”,其中 Unicode 为 0x24B62,₤ 为 0x00A3。所以我必须将字符串组合为“abc0x24B62def0x00A3ghi”。0x 将考虑可以包含在其中的所有值。因此,如果您想打印“abc62”,则字符串将为“abc0x24B6262”。整个字符串不会被视为 0x 内的 4 字节 unicode (0x24B6262) 值吗?如何解决这个问题?如何打印“abc62”而不是 abc(0x24B6262)?

  1. 我有一个字符串const char* tmp = "abc\x0fdef";。当我使用printf("\n string = %s", tmp);then 打印时,它将打印 abcdef。这里是哪里0f?我知道\x0f 的十进制值将存储在字符串中,即15,所以当我们尝试打印时,应该打印15 对吗?我的意思是,它应该是“abc15def”,但它只打印“abcdef”。
4

1 回答 1

3

我认为您可能对编码的概念不熟悉,从阅读您的帖子。

例如,您说“... ₤ 的 unicode 是 0x00A3”。这是真的 - unicode 代码点 U+00A3 是井号。但是 0x00A3 不是您表示井号的方式,例如 UTF-8(Unicode 的一种特殊常见编码)。看看这里,看看我的意思。如您所见,U+00A3 的 UTF-8 编码是两个字节 is 0xc2, 0xa3(按此顺序)。

printf()在您拨打电话和屏幕上出现某些内容之间会发生几件事。

首先,您的程序运行代码printf("abc\x0fdef"),这意味着按顺序将以下字节写入程序的标准输出:

0x61, 0x62, 0x63, 0x0f, 0x64, 0x65, 0x66

注意:我假设您的源代码是 ASCII(或 UTF-8),这很常见。从技术上讲,我相信对源代码字符集的解释是实现定义的。

现在,为了查看输出,您通常会在某种 shell 中运行该程序,并且它最终必须将这些字节转换为可视字符。它通过使用编码来做到这一点。同样,与 ASCII 兼容的东西很常见,例如 UTF-8。在 Windows 上,CP1252 很常见。

如果是这种情况,您将获得以下映射:

0x61 - a
0x62 - b 
0x63 - c
0x0f - the 'shift in' ASCII control code
0x64 - d
0x65 - e
0x66 - f

这将打印为“abcdef”,因为“移入”控制代码是非打印字符。

注意:上面的内容可能会根据所涉及的确切字符集而改变,但除非您有特殊的设置,否则您很可能正在处理 ASCII 或 UTF-8。

如果你有一个 UTF-8 兼容的终端,下面应该打印出“abc₤def”,作为一个让你开始的例子:

printf("abc\xc2\xa3def");

说得通?


更新:要回答您评论中的问题:您需要区分代码点和该代码点编码的字节值。

Unicode 标准定义了“代码点”,它们是字符的数值。这些通常写为 U+XYZ,其中 XYZ 是十六进制值。例如,字符 U+219e 是向左的两个箭头。这也可能写为 0x219e。你会从上下文中知道作者正在谈论一个代码点。

当您需要对该代码点进行编码(打印或保存到文件等)时,您可以使用编码,例如 UTF-8。请注意,例如,如果您使用UTF-32编码,则每个代码点都与编码值完全对应。所以在 UTF-32 中,代码点 U+219e 确实会被简单地编码为 0x219e。但是其他编码会做不同的事情。UTF-8 会将 U+219e 编码为三个字节0xE2 0x86 0x9E

最后,\x符号只是您如何在 C/C++ 引用字符串中写入任意字节值。如果我用 C 源代码编写,"\xff"那么内存中的字符串将是两个字节0xff 0x00(因为它会自动获得一个空终止符)。

于 2013-05-26T06:16:26.077 回答