我有与Unicode相关的问题,在const char*
打印转义的十六进制值。
现在在编写Unicode字符串时,假设您要编写“abcdef₤ghi”,其中Unicode为0x24B62且₤为0x00A3。所以我将把字符串组成“abc0x24B62def0x00A3ghi”。 0x将考虑可以包含在其中的所有值。因此,如果要打印“abc62”,字符串将为“abc0x24B6262”。整个字符串不会被视为在0x内考虑的4字节unicode(0x24B6262)值吗?怎么解决这个?如何打印“abc62”而不是abc(0x24B6262)?
const char* tmp = "abc\x0fdef";
。当我使用printf("\n string = %s", tmp);
打印时,它将打印abcdef。 0f
在哪里?我知道\ x0f的十进制值将存储在字符串中,即15,所以当我们尝试打印时,应该打印15?我的意思是,它应该是“abc15def”,但它只打印“abcdef”。答案 0 :(得分:2)
我认为你可能不熟悉编码的概念,从阅读你的帖子。
例如,你说“un的unicode是0x00A3”。这是真的 - unicode代码点U + 00A3是英镑符号。但0x00A3并不是你如何表示英镑符号,例如,UTF-8(Unicode的一种特殊常见编码)。拿一个look here来看看我的意思。如您所见,U + 00A3的UTF-8编码是两个字节0xc2
,0xa3
(按此顺序)。
在致电printf()
和屏幕上显示某些内容之间,有几件事情发生。
首先,您的程序运行代码printf("abc\x0fdef")
,这意味着按顺序将以下字节写入您的程序的stdout:
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”,因为'shift in'控制代码是非打印字符。
注意:上述内容可能会根据所涉及的确切字符集而改变,但除非您有异国情调的设置,否则您正在处理的是ASCII或UTF-8。
如果您有兼容UTF-8的终端,以下内容应打印出“abc₤def”,这只是为了让您入门:
printf("abc\xc2\xa3def");
有意义吗?
更新:要回答评论中的问题:您需要区分 codepoint 和编码的字节值码点。
Unicode标准定义了“代码点”,它们是字符的数值。这些通常写为U + XYZ,其中XYZ是十六进制值。 例如,字符U + 219e是LEFTWARDS TWO HEADED ARROW。 这也可能写成0x219e。你会从上下文中知道作者正在谈论一个代码点。
当您需要对该代码点进行编码(打印或保存到文件等)时,您使用编码,例如UTF-8。请注意,如果您使用了UTF-32编码,则每个代码点都与编码值完全对应。因此在UTF-32中,代码点U + 219e确实将被编码为0x219e。但其他编码将以不同的方式做事。 UTF-8将U + 219e编码为三个字节0xE2 0x86 0x9E
。
最后,\x
表示法只是在C / C ++引用字符串中编写任意字节值的方式。如果我用C源代码编写"\xff"
,那么内存中的那个字符串将是两个字节0xff 0x00
(因为它会自动获得一个空终止符)。