例如我有这个结构
struct A {
float x;
float y;
float z;
};
我可以这样做吗? A a; float* array = (float*)&a;
并使用as float数组?
答案 0 :(得分:27)
不,对数组进行类型转换struct
将不起作用。允许编译器在成员之间添加填充。
数组之间没有填充。
注意:没有什么可以阻止你进行投射,但是,在投射后使用值导致未定义的行为。
答案 1 :(得分:22)
在实际意义上,是的,你可以做到,它将适用于所有最常用的架构和编译器。
请参阅维基百科上的"Typical alignment of C structs on x86"部分。
更多详情:
浮点数是4个字节,不会插入填充( 几乎所有情况)。
大多数编译器也可以选择指定结构的打包,你可以强制不插入填充(即Visual Studio中的#pragma pack)
保证数组在内存中是连续的。
你能保证它能在所有编译器中使用世界上所有的CPU吗?不......但我肯定希望看到一个失败的平台:)
编辑:如果有填充字节,添加static_assert(sizeof(A) == 3*sizeof(float))
将使代码无法编译。所以,当你编译时,你确定它是有效的。
答案 2 :(得分:18)
这是一种严格的别名冲突,简单明了。除了第一个元素之外,对该指针的任何访问都是未定义的行为。在更复杂的情况下,无论您访问哪个元素,它都只是简单的未定义行为。
如果需要数组,请使用数组。 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
}
的重载,因此您可以使用它来命名每个单独的数组成员:
{{1}}
答案 3 :(得分:5)
对于g ++,您可以使用struct的属性,如下所示:
struct A {
float x;
float y;
float z;
}__attribute__((__packed__));
禁用结构对齐。
答案 4 :(得分:4)
你可以这样做,直到编译器开始优化,然后出错。
使用指向第一个元素的指针访问结构的第一个元素是未定义的行为。 &#34;未定义的行为&#34;意味着什么都可能发生。编译器可以假定没有未定义的行为。
编译器可以从中推断出许多后果:如果编译器知道你的float *指向结构的第一个元素,那么它可以推断出该数组的每个索引都等于0(因为其他任何东西都是未定义的)行为)。如果编译器不知道这一点,那么它可以推断出数组指针不能指向结构,并且改变数组元素不能改变结构元素,反之亦然。
你能看出这会怎么样吗?