C 为什么作为命令行参数传入时UTF-16字符串的hextump与直接在终端上传递的不同?

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

在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("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));