这个问题是关于使用带结构偏移量的指针算法派生的指针。
考虑以下程序:
#include <cstddef>
#include <iostream>
#include <new>
struct A {
float a;
double b;
int c;
};
static constexpr auto off_c = offsetof(A, c);
int main() {
A * a = new A{0.0f, 0.0, 5};
char * a_storage = reinterpret_cast<char *>(a);
int * c = reinterpret_cast<int *>(a_storage + off_c));
std::cout << *c << std::endl;
delete a;
}
这个程序似乎可以在我测试的编译器上运行并给出预期的结果,使用默认设置和 C++11 标准。
(一个密切相关的程序,我们使用 void *
而不是 char *
和 static_cast
而不是 reinterpret_cast
,
没有被普遍接受。 gcc 5.4
发出关于指针算术带有 void 指针的警告,clang 6.0
表示该指针
使用 void *
的算术是错误的。)
根据 C++ 标准,该程序是否具有明确定义的行为?
答案是否取决于实现是放宽还是严格的指针安全 ([basic.stc.dynamic.safety]
)?
最佳答案
您的代码中没有基本错误。
如果 A
不是普通的旧数据,则以上是 UB(C++17 之前)和有条件支持(C++17 之后)。
您可能想用 auto*
替换 char*
和 int*
,但这是一种风格。
请注意,指向成员的指针以类型安全的方式执行完全相同的操作。大多数编译器实现一个指向成员的指针 ... 作为成员在类型中的偏移量。然而,它们确实可以在任何地方工作,甚至在非 Pod 结构上也是如此。
旁白:我看不到 offsetof
是标准中的 constexpr
的保证。 ;)
无论如何,替换:
static constexpr auto off_c = offsetof(A, c);
与
static constexpr auto off_c = &A::c;
和
auto* a_storage = static_cast<char *>(a);
auto* c = reinterpret_cast<int *>(a_storage + off_c));
与
auto* c = &(a->*off_c);
以 C++ 方式完成。
关于c++ - C++ 中的结构偏移量和指针安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46123867/