我可以安全地将浮点数的结构转换为浮点数组吗C++?

Can I safely convert struct of floats into float array in C++?

本文关键字:数组 C++ 转换 安全 浮点数 结构 我可以      更新时间:2023-10-16

例如我有这个结构

struct  A {
float x;
float y;
float z;
};

我可以这样做吗?A a; float* array = (float*)&a;并使用 as 浮点数组?

在实际意义上,是的,你可以这样做,它将适用于所有最常用的架构和编译器。

请参阅维基百科上的"x86 上 C 结构的典型对齐方式"部分。

更多详情:

  • 浮点数为 4 个字节,不会插入填充(在几乎所有情况下(。

  • 此外,大多数编译器都可以选择指定结构的打包,并且可以强制不插入填充(即来自Visual Studio的 #pragma 包(

  • 数组保证在内存中是连续的。

你能保证它能在世界上所有的CPU上用所有的编译器工作吗?哈哈。但我绝对希望看到一个失败的平台:)

编辑:如果有填充字节,添加static_assert(sizeof(A) == 3*sizeof(float))将使此代码无法编译。因此,您将确保它在编译时可以正常工作。

不,将struct类型转换为数组将不起作用。允许编译器在成员之间添加填充

数组在成员之间没有填充。

注意:没有什么可以阻止您进行强制转换,但是,在转换后使用值会导致未定义的行为。

这是一个严格的混叠冲突,简单明了。在该指针的任何访问中,指向除第一个元素之外的任何元素都是未定义的行为。在更复杂的情况下,无论您访问哪个元素,它都只是普通的未定义行为。

如果需要数组,请使用数组。std::array还有一个重载 for forstd::get,所以你可以用它来命名每个单独的数组成员:

using A = std::array<float, 3>;
enum AElement { X, Y, Z };
int main() {
A a;
get<X>(a) = 3.0f; // sets X;
float* array = a.data(); // perfectly well defined
}

对于 g++,你可以对结构使用属性,如下所示:

struct  A {
float x;
float y;
float z;
}__attribute__((__packed__));

它禁用结构对齐。

你可以这样做,直到编译器开始优化,然后出现问题。

使用指向第一个元素的指针访问结构的第一个元素以外的任何元素都是未定义的行为。"未定义的行为"意味着任何事情都可能发生。编译器可以假定没有未定义的行为。

编译器可以从中推断出许多后果:如果编译器知道您的 float* 指向结构的第一个元素,那么它可以推断出该数组的每个索引都等于 0(因为其他任何内容都是未定义的行为(。如果编译器不知道这一点,那么它可以推断数组指针不能指向结构,并且更改数组元素不能更改结构元素,反之亦然。

你能看到这将如何出错吗?