如果编码和宽度相同,则将字符串从“wchar_t”转换为“char16_t”是否合法?

Hum*_*ler 5 c++ strict-aliasing undefined-behavior language-lawyer c++17

在 Windows 上,wchar_t是 UTF-16(LE) 格式的字符,在很大程度上相当于char16_t. 然而,这两种字符类型在 C++ 类型系统中仍然是不同的类型——这使我不确定根据 C++ 标准,这两种字符类型的序列之间的转换是否合法。

我的问题是:在 C++17 中,执行以下转换并读取转换后的指针是否合法:

  • reinterpret_cast<const wchar_t*>(char16_ptr)哪里decltype(char16_ptr)const char16_t*, 和
  • reinterpret_cast<const char16_t*>(wchar_ptr)哪里decltype(wchar_ptr)const wchar_t*

出于本问题的目的,假设以下情况:

  • sizeof(wchar_t) == sizeof(char16_t), 和
  • wchar_t格式相同char16_t(如 Windows 上的情况)

基本上,这是否违反了严格别名?

我的理解是,由于 ,转换[expr.reinterpret.cast]/7本身是有效的,但是转换的结果不能安全地使用,因为该类型被不是charunsigned char或 的东西别名std::byte。这个解释正确吗?


注意:已经提出了关于相同问题的其他问题wchar_tchar16_t但据我所知,这个问题与这些问题并不重复。值得注意的是,问题“ wchar_t 和 char16_t 在 Windows 上是否相同? ”实际上执行了reinterpret_cast指针之间的操作,但没有一个答案实际上首先解决了这种转换是否合法。

Nic*_*las 6

你已经知道这个问题的答案:严格来说,不

wchar_t不是char16_t。两者都不是从对方派生出来的。两者都不相似。两者都不是另一个的签名/未签名版本。两者都不是包含另一个的聚合。而且它们都不是字节类型(char等)。

因此,您无法wchar_t通过对 a 的指针/引用来访问 a char16_t

如果严格避免严格别名是您的目标,则必须将数据复制到不同的对象。这有效的,假设它们都有相同的表示。