使用从别名“byte”指针派生的“T”指针的合法性
在C ++中,它是合法的char,unsigned char或std::byte指向别名任何T指针。这种别名指针能够访问原始内存中的对象表示。
我的问题是它是否是合法的和游离的未定义的行为,以使用一个T*从算术上派生的指针char/ unsigned char/std::byte指针混叠的原始T阵列对象序列-前提条件是所得指针仍然正确地对准和混叠序列的原始可达性内. 作为一个具体的例子:
// Array sequence is 2 in length
auto array = std::array<unsigned,2>{0xdead, 0xbeef};
// Derive the address of &array[1] using std::byte pointer
auto p = reinterpret_cast<std::byte*>(array.data());
auto p1 = reinterpret_cast<unsigned*>(p + sizeof(unsigned));
assert(p1 == &array[1]); // This expression should be legal since the pointer is safely derived
assert(*p1 == array[1]); // But is this legal, as per the C++ standard?
p1在上面的例子中应该安全地导出指针,因为它没有超出array's bound的可达性。我知道在 C++ 中的许多情况下,将指针转换为实际上无法使用/取消引用的类型/表示是合法的。就标准而言,此处的结果指针是否合法取消引用?
出于这个问题的目的,假设它T可能不是标准布局类型。
注意:我不是在问这在实践中是否可行,因为我还没有看到这种类型的代码在编译器上失败;但我很想知道严格来说这是否符合 C++ 标准。
编辑:
我不想破坏这个问题,但有一些评论断言[expr.add]p + sizeof(unsigned)是未定义行为,特别是引用[expr.add]/4和[expr.add]/ 6由于实际上不是字节数组。p
事实上,有一个字节序列[1],而[expr.add]/4和[expr.add]/6根本不适用[2]
[1]: char, unsigned char, 和std::byte查看对象的对象表示,在[basic.types.general]/4下定义为:
类型对象的对象表示是类型对象占用
T的Nunsigned char对象序列T,其中N等于sizeof(T)。
上述装置存在是正式序列unsigned char(其std::byte是能够表示的),这意味着p + sizeof(unsigned)是有效的。我们不是通过类似的指针查看,我们正在查看的正是合法的底层对象表示。
[2]: [expr.add]/4只是指数组对象的可达性。然而,正如上文指出的,是一个有效的和可及对象,由于unsigned char顺序,我们不超过可达性-因此这并不适用于作为未定义行为的情形。
据我所知,[expr.add]/6 的存在主要是为了避免派生类型的数组被强制转换为基指针并试图被索引的情况。但是它不适用于这种情况,因为我们不是通过“类似”指针查看,我们正在查看正式定义为unsigned chars序列的对象表示。这不是类似的表示,而是准确的。