c++ - C++ 中的结构偏移量和指针安全

标签 c++ c++11 pointers language-lawyer offsetof

这个问题是关于使用带结构偏移量的指针算法派生的指针。

考虑以下程序:

#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/

相关文章:

c++ - 使用 C 代码执行 Bash 命令

c++ - C++11 中的 auto 关键字奇怪行为

c++ - 将 `-std=c++11` 传递给 CMakeLists?

从不同大小的整数转换为指针

c++ - 如何避免waf中的库多次检查?

c++ - 我需要构建 TinyThread++ 吗?

c++ - VC++允许/##/作为宏的值——如何在eclipse/mingw-gcc中处理它?

c++ - 如何生成像列表理解这样的 vector

c - 在函数中分配多维数组

c++ - 如何保持存储在作为参数传递的指针中的地址在所有函数调用中保持一致