C 为什么作为命令行参数传入时UTF-16字符串的hextump与直接在终端上传递的不同?
在bash中,我可以通过执行以下操作获得字符串C 为什么作为命令行参数传入时UTF-16字符串的hextump与直接在终端上传递的不同?,c,bash,utf-16,hexdump,libiconv,C,Bash,Utf 16,Hexdump,Libiconv,在bash中,我可以通过执行以下操作获得字符串hello的hextump作为UTF-16: $ echo -n "hello" | iconv -f ascii -t utf-16 | hexdump 0000000 feff 0068 0065 006c 006c 006f 000000c 我还可以编写一个简短的C程序,如下所示: int main(int argc, char **argv) { char *str = argv[1]; hexDump("T
hello
的hextump作为UTF-16:
$ echo -n "hello" | iconv -f ascii -t utf-16 | hexdump
0000000 feff 0068 0065 006c 006c 006f
000000c
我还可以编写一个简短的C程序,如下所示:
int main(int argc, char **argv) {
char *str = argv[1];
hexDump("The string", str, 12);
return 0;
}
使用中的hextump
例程12
是我使用上面的hextump
计算的字节数
编译并运行:
$ gcc test.c -o test
$ ./test $(echo -n hello | iconv -f ascii -t utf-16)
The string:
0000 ff fe 68 65 6c 6c 6f 00 53 53 48 5f ..hello.SSH_
为什么第一个六角字符串feff 0068 0065 006c 006c 006f
和第二个六角字符串ff fe 68 65 6c 6c 6f 00 53 53 48 5f
之间存在差异
我问这个问题是因为我试图调试一个应用程序,它使用libiconv
将UTF-16字符串转换为UTF-8,并不断得到errno
的EILSEQ
,这意味着libiconv
遇到了一个“无效的多字节序列”
更新:
如果我使用-C
运行hextump
,我会得到以下输出:
$ echo -n hello | iconv -f ascii -t utf-16 | hexdump -C
00000000 ff fe 68 00 65 00 6c 00 6c 00 6f 00 |..h.e.l.l.o.|
0000000c
这个十六进制字符串仍然不同于我的C程序生成的字符串,因为它包含散布在ascii字符之间的
\x00
字节。然而,当我运行C程序时,根本没有\x00
字节。它只有ff fe
头和常规ascii字符。命令echo-n hello | iconv-f ascii-t utf-16 | hextump-C
只是在程序之间直接传输数据。iconv输出的任何字节都直接作为hexdump的输入
通过命令/test$(echo-n hello | iconv-f ascii-t utf-16)
,shell获取iconv的输出,并有效地将其粘贴到新命令中,解析新命令,然后执行它
所以从iconv中出来的字节是:“fffe680065006c006c006f00”,shell解析这个。在解析时,shell似乎只是跳过空字节,因此程序的参数输入只是非空字节。因为您的字符串是ascii,这意味着结果只是一个ascii字符串(前面是UTF-16 BOM)
我们可以使用像U+3300这样的字符来演示这一点(㌀). 如果我们传递的是这个字符而不是ascii字符,并且上面的内容是正确的,那么输出将包括0x33(数字“3”)
我的终端恰好使用UTF-8,它支持字符U+3300,因此我将iconv从该字符转换为UTF-16。我得到输出:
The string:
0000 ff fe 33 ..3
顺便说一下,您的程序包含阵列的硬编码大小:
hexDump("The string", str, 12);
你真的不应该这样做。如果数组没有那么大,那么你会得到未定义的行为,并且你的帖子显示在实数参数之后打印出一些垃圾(垃圾似乎是环境变量数组的开头)。这真的没有理由。只需使用正确的值:
hexDump("The string", str, strlen(str));
这似乎是一个小小的Endian vs Big Endian的问题。我认为你问题的根本问题与你认为你是如何导入它的关系不大,而是操作系统在语言环境方面允许argv被编码成什么?请参阅Unix约定,以及更多与argv相关的优点。我想知道是否有办法禁用shell行为您描述:“在解析时,shell似乎只是跳过空字节”。
hexDump("The string", str, strlen(str));