std::wstring 的标准定义字节顺序是啥?

Posted

技术标签:

【中文标题】std::wstring 的标准定义字节顺序是啥?【英文标题】:What's the standard-defined endianness of std::wstring?std::wstring 的标准定义字节顺序是什么? 【发布时间】:2013-02-04 18:24:29 【问题描述】:

我知道 UTF-16 有两种字节序:大字节序和小字节序。

C++ 标准是否定义了 std::wstring 的字节顺序?还是实现定义的?

如果是标准定义的,C++标准的哪个页面提供了关于这个问题的规则?

如果是实现定义的,如何确定?例如在 VC++ 下。编译器是否保证 std::wstring 的字节序严格依赖于处理器?

我必须知道这一点;因为我想将 UTF-16 字符串发送给其他人。我必须在 UTF-16 字符串的开头添加正确的 BOM 以指示其字节顺序。

简而言之:给定一个 std::wstring,我应该如何可靠地确定它的字节序?

【问题讨论】:

该标准甚至没有指定wchar_t 的大小,它不会给出字节顺序。 为什么你需要知道这个?字节序主要取决于架构。 @EalGray,我必须知道这一点,因为我想将 UTF-16 字符串发送给其他人。我必须在开头添加正确的 BOM。 wstring 完全是实现定义的...如果您要与他人交流,would be kind of you to use UTF-8 instead 不会遇到所有这些问题。 @xmllmx: 1) 如果它已经在内存中,你不需要知道字节序。就像您对整数求和时不关心整数的字节序一样。等于 0x0123 的 wchar_t 表示任何使用 UTF-16 处理 wchar_t 字符串的平台上的代码点 U+0123。 2)“编译器填充字符”?你的意思是“字符串文字”吗?那么如何使用 UTF-8 字符串文字,在 C++11 中以 u8"????" 的形式提供,或者在其他编译器上以 "????" 的形式提供(在链接中描述)? 【参考方案1】:

字节序取决于机器,而不是语言。 Endianess 由处理器定义,以及它如何安排数据进出内存。在处理 wchar_t(比单个字节宽)时,处理器本身在读取或写入时会根据需要对齐多个字节,以便再次将其读取或写入 RAM。代码只是将其视为处理器内部寄存器中表示的 16 位(或更大)字。

为了确定(如果这确实是您想要做的)字节序(您自己),您可以尝试将一个已知的 32 位(无符号整数)值写入 ram,然后使用 char 指针将其读回。查找返回的排序。

看起来像这样:

unsigned int aVal = 0x11223344;
char * myValReadBack = (char *)(&aVal);

if(*myValReadBack == 0x11) printf("Big endian\r\n");
else                       printf("Little endian\r\n");

我确定还有其他方法,但是类似上面的方法应该可以,不过请检查我的小与大:-)

此外,在 Windows RT 之前,VC++ 真的只能编译为英特尔类型的处理器。他们真的只有一种字节序类型。

【讨论】:

谢谢。 MSDN 的哪个页面指定“VC++ 真的只编译到英特尔类型的处理器。他们真的只有 1 个字节序类型。”? @xmllmx - 没有 MSDN 会这么说。这是我自己的结论。 VC++ 是微软的 C++ 编译器。 Windows 仅在 X86 处理器上存在 Windows 8 RT。 X86 处理器一直都是 Little Endian。看这里:en.wikipedia.org/wiki/Endianness。现在,如果您要发送到大端机器或从大端机器接收,您可能必须转换为/从,但如果您要做的只是了解您自己的内部机器的端类型,这甚至不需要代码,您应该只能够知道(在你的情况下是“小端”) @trumpetlicks Windows 早在 Windows RT 之前就已经存在于非 x86 平台(例如 PPC),Visual C++ 也存在于它之上。但是,我确实记得读过它从来都不是小端序。一些处理器确实支持大端模式和小端模式,但 Windows 要求这些处理器以小端模式运行。 @hvd 我以为你可能错了,但***同意你的观点:en.wikipedia.org/wiki/… 啊,我在哪里看到的:"A decision was made VERY long ago that Windows would not be ported to a big-endian processor. And as far as I can see, that's going to continue. Since almost all the new processors coming out are either little-endian, or swing both ways (this is true of all the RISC machines Windows has supported, for example), this isn't really a big deal."【参考方案2】:

它是实现定义的。 wstring 只是 wchar_t 的字符串,它可以是任何字节顺序,也可以是任何旧大小。

【讨论】:

如果是实现定义的,那么如何确定呢?例如VC++下。 它将包含您放入其中的任何内容。在 VC++ 上,wchar_t 是 16 位的,如果您从 WinAPI 获取字符串,它们将具有本机硬件字节顺序。【参考方案3】:

wchar_t 内部不需要是 UTF-16,UTF-16 字节序不会影响 wchar 的存储方式,只是保存和读取它的问题。

在将它发送到任何地方之前,您必须使用将 wstring 转换为 UTF-16 字节流的显式过程。 wchar 的内部字节序依赖于体系结构,最好使用一些不透明的接口进行转换,而不是尝试手动转换。

【讨论】:

编译器是否保证 std::wstring 的字节序严格依赖于处理器? @xmllmx 不,它没有。这就是为什么我建议不要弄乱 wstring 的内部结构并使用一些标准接口来正确转换它。 问题仍未解决。给定一个 std::wstring,我应该如何可靠地确定它的字节顺序?【参考方案4】:

为了发送正确的 BOM,您不需要知道字节顺序。只需使用代码 \uFEFF。这将是 bigendian 或 little-endian,具体取决于您的实现的字节序。您甚至不需要知道您的实现是 UTF-16 还是 UTF-32。只要是某种 unicode 编码,您就会得到相应的 BOM。

不幸的是,wchars 和宽流都不能保证是 unicode。

【讨论】:

以上是关于std::wstring 的标准定义字节顺序是啥?的主要内容,如果未能解决你的问题,请参考以下文章

ustring - std::string/std::wstring 的就地替换?

将 std::wstring 移植到 gcc cygwin

BSTR 到 std::string (std::wstring) 反之亦然

将 std::wstring 从 Visual Studio 移植到 mingw gcc

std::wstring to_wstring(双值); [复制]

宽字符std::wstring的长度和大小问题?sizeof(std::wstring)是固定的32,说明std::wstring是一个普通的C++类,而且和Delphi不一样,没有负方向,因为那个需