【问题标题】:Is it valid to cast pointer to struct to array pointer将指向结构的指针转换为数组指针是否有效
【发布时间】:2017-01-19 14:23:05
【问题描述】:

给定一个聚合结构/类,其中每个成员变量都是相同的数据类型:

struct MatrixStack {
    Matrix4x4 translation { ... };
    Matrix4x4 rotation { ... };
    Matrix4x4 projection { ... };
} matrixStack;

将其强制转换为其成员数组的有效性如何?例如

const Matrix4x4 *ptr = reinterpret_cast<const Matrix4x4*>(&matrixStack);
assert(ptr == &matrixStack.translation);
assert(ptr + 1 == &matrixStack.rotation);
assert(ptr + 2 == &matrixStack.projection);
auto squashed = std::accumulate(ptr, ptr + 3, identity(), multiply());

我这样做是因为在大多数情况下,为了清楚起见,我需要命名成员访问权限,而在其他一些情况下,我需要将数组传递给其他 API。通过使用 reinterpret_cast,我可以避免分配。

【问题讨论】:

  • 我的理解是,使用除非使用 reinterpret_cast 否则无法编译的强制转换结果几乎总是冒未定义行为的风险。这种特殊情况可能会按预期工作(除非您的编译器弄乱了结构对齐,因此 Matrix4x4 成员在内存中不完全连续),但标准仍然不能保证。
  • 它可能有效,也可能无效,取决于 Matrix4x4 实际大小和数据对齐设置
  • 结构可以有填充,而arrays never have padding
  • @antred,前提是 Matrix4x4 与 int 对齐(并且我确实可以控制它),并且该结构是严格非虚拟的,它仍然是编译器在之前填充的一个很好的理由第一个成员及其成员之间?这不是一个反问,我只是想知道一些极端情况。

标签: c++ c++11 pointers struct casting


【解决方案1】:

演员不需要按标准工作。

但是,您可以通过使用静态断言来确保您的代码安全,如果违反假设,将阻止代码编译:

static_assert(sizeof(MatrixStack) == sizeof(Matrix4x4[3]), "Size mismatch.");
static_assert(alignof(MatrixStack) == alignof(Matrix4x4[3]), "Alignment mismatch.");
// ...
const Matrix4x4* ptr = &matrixStack.translation;
// or
auto &array = reinterpret_cast<const Matrix4x4(&)[3]>(matrixStack.translation);

【讨论】:

  • 你不是说== 在两个sizeof/alignof 参数之间吗?
  • 也许添加一个检查 offsetof(MatrixStack, translation)==0。第一个元素是否总是保证偏移量为零?我们可以检查其他两个成员是否具有预期的偏移量。
  • 使用静态断言进行验证的良好调用。谢谢马克西姆
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-21
  • 1970-01-01
  • 2015-01-24
  • 2017-06-03
  • 2014-07-22
  • 1970-01-01
相关资源
最近更新 更多