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

Sem*_*nko 30 c++

例如,我有这个结构

struct  A {
    float x;
    float y;
    float z;
};
Run Code Online (Sandbox Code Playgroud)

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

Tho*_*ews 27

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

数组之间没有填充.

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

  • 在一般意义上,你可能是对的,但从实际的角度来看,这将适用于Windows,Linux和嵌入式平台下的几乎所有编译器,如PowerPC和我使用的arm.我当然希望看到一个失败的例子:) (5认同)
  • 顺便说一下,我希望托马斯说过用这种方式进行类型转换是不安全的,而不是说它不会起作用. (4认同)

Sil*_*Sil 24

实际上,是的,你可以做到这一点,它将适用于所有最常用的架构和编译器.

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

更多细节:

  • 浮点数是4个字节,不会插入填充(几乎所有情况下).

  • 大多数编译器也可以选择指定结构的打包,你可以强制不插入填充(即Visual Studio中的#pragma pack)

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

你能保证它能在所有编译器中使用世界上所有的CPU吗?不..但我肯定希望看到一个失败的平台:)

编辑:static_assert(sizeof(A) == 3*sizeof(float))如果有填充字节,添加将使此代码无法编译.那么你将确保它在编译时有效.

  • 我喜欢这个答案,因为它更倾向于实用主义而不是规范的迂腐应用. (4认同)

Sto*_*ica 19

这是一种严格的别名违规,简单明了.除了第一个元素之外,对该指针的任何访问都是未定义的行为.而在更复杂的情况下,无论您访问哪个元素,它都只是简单的未定义行为.

如果需要数组,请使用数组.std::array也有for的重载std::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
}
Run Code Online (Sandbox Code Playgroud)

  • 我不认为这是严格的别名冲突,因为指针和struct元素都是“ floats”。 (3认同)
  • @PasserBy - 因此我的观点是第一个成员由于标准布局类型保证而没问题.但就标准本身而言,这就是你. (3认同)
  • @Jeff - 呃,不.仅允许访问**第一个**成员,因为这是标准布局类型.该子句并不意味着即使没有填充,也可以将结构视为数组.这里的相关内容是`reinterpret_cast`的描述,这是在这里进行的演员表. (2认同)

Pav*_*vel 6

对于g ++,您可以使用struct的属性,如下所示:

struct  A {
    float x;
    float y;
    float z;
}__attribute__((__packed__));
Run Code Online (Sandbox Code Playgroud)

它禁用了struct alignment.