【问题标题】:reinterpret_cast between char* and std::byte*char* 和 std::byte* 之间的 reinterpret_cast
【发布时间】:2021-11-23 15:33:37
【问题描述】:

我正在阅读type aliasing rules,但无法确定此代码中是否包含 UB:

std::vector<std::byte> vec = {std::byte{'a'}, std::byte{'b'}};
auto sv = std::string_view(reinterpret_cast<char*>(vec.data()), vec.size());
std::cout << sv << '\n';

我很确定它不会,但我经常对 C++ 感到惊讶。 reinterpret_cast 是否始终位于 char*unsigned char*std::byte* 之间?

此外,constaddition 在这种演员阵容中是否合法,例如:

std::array<char, 2> arr = {'a', 'b'};
auto* p = reinterpret_cast<const std::byte*>(arr.data());

再次,我怀疑它是合法的,因为它说

AliasedType 是 DynamicType 的(可能是 cv 限定的)有符号或无符号变体

但我想一劳永逸地确定reinterpret_casting。

【问题讨论】:

  • 相关问题:What is the strict aliasing rule? 但是,这个问题不是很具体,因为它不区分 C 和 C++,尽管两种语言的规则不同。
  • 如果我们假设vec.data()给出了一个指向数组元素的指针,然后在sv中对该指针的reinterpret_cast&lt;char*&gt;-ed值进行指针运算,那么它就违反了timsong-cpp.github.io/cppwp/n4868/expr.add#6.sentence-1 .
  • @LanguageLawyer 你能扩展一下吗?
  • 扩展什么?指向std::byte 类型对象的char* 类型指针不能用于指针算术。如果您不将所有内容隐藏在库函数调用后面并明确公开它们所做的基本事情,那么推理您的代码会容易得多。
  • 我看不出图书馆在哪里可以做这样的算术。 std::byte b[2]; reinterpret_cast&lt;char*&gt;(&amp;b[1]) - reinterpret_cast&lt;char*&gt;(&amp;b[1]);我不认为这是 UB。 vec.data() 提供指向数组元素的指针,但它是否被重新解释为 char*。例如,这个char* 可以从另一个char* 中减去,不是吗?

标签: c++ language-lawyer reinterpret-cast


【解决方案1】:

代码没问题。

标准允许char*std::byte* 为任何指针类型起别名。 (小心,反之亦然)。

([basic.types]/2):

对于平凡的任何对象(基类子对象除外) 可复制类型 T,无论对象是否拥有类型的有效值 T,构成对象的底层字节([intro.memory])可以是 复制到 char、unsigned char 或 std​::​byte 的数组中 ([cstddef.syn]).43 如果该数组的内容被复制回 对象,该对象随后应保持其原始值。

([basic.lval]/8.8):

如果程序尝试通过以下方式访问对象的存储值 行为是以下类型之一以外的左值 未定义:

  • char、unsigned char 或 std​::​byte 类型。

是的,您可以添加const

【讨论】:

  • 您的答案涵盖访问,但不包括指针运算。
猜你喜欢
  • 2013-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-13
  • 1970-01-01
  • 2021-12-28
  • 2013-10-18
相关资源
最近更新 更多