struct Point
{
double X;
double Y;
};
Q1)是以下便携式(编译器/机器)
Point point = { 1.1, 2.2 };
double arr[2] = {};
memcpy(arr, point, sizeof(double)*2);
Q2)结构数组
相同Point *pPoints = new Point[numPoints];
double *pArr = new double[2*numPoints];
memcpy(pArr, pPoints, sizeof(double)*2*numPoints);
在Windows / MSVC上的我希望两者都能成功。
编辑: 我不是要为每个可能的结构/类别问这些问题;我要求结构“Point”的这种特殊情况(注意:只有2个pod,没有virtualmember / user构造函数/用户构造函数)。这可能是一个C问题,它与编译器的结构对齐和内存布局有关。
到目前为止,我已经知道c / c ++标准没有对Point的布局强制执行任何操作,因此我必须使用静态断言来确保它,对吗?
答案 0 :(得分:8)
您的代码假设sizeof(struct Point) == 2*sizeof(double);
。这是一个危险的假设,因为当你编写和测试代码时它会是真的,但它确实是运气,而不是定义。运气有一种不久的习惯:)
在这种情况下,您很可能永远不会遇到问题(因为struct Point
的定义不太可能发生变化,并且机器对齐问题也不太可能在这种类型的可移植性方面)。话虽如此,基于代码的方式是一种可怕的模式。
答案 1 :(得分:0)
理论上,struct可以在成员之间和结束之后填充。所以它不一定与普通双打布局兼容。但是如果你添加0 packing和static_assert来确保sizeof(Point)== 2 * sizeof(double)我在实践中看不到失败的方法。
答案 2 :(得分:0)
好吧,让我们从完全支持@mah所说的事实开始。确实这很可怕,如果可能应该避免。
但是,有时,这是不可能的。例如,您有时需要采用其他方式:您已收到按特定顺序排列的数字流,并且您希望将其“解压缩”到结构中以便更好地处理。这就是需要严格控制内存布局的地方。
在这种情况下,如果可以使用struct Point
正确的包装指令来装饰#pragma pack(1)
可能告诉编译器不添加任何对齐。
请注意,这是#pragma。虽然有些可能看起来有点普遍,但根据定义编译器/平台特定。一定要添加一些简单的断言,检查sizeofs是否真的相同,以防你更改编译器或将其升级到以不同方式处理pragma的版本。
假设你的编译器已经理解了pack(1)pragma(或类似的),你的代码将是安全的,并且这样的POD结构的sizeof确实等于2 * double。在这里查看好的示例https://stackoverflow.com/a/3318475/717732
我实际上不记得在数组中打包。我几乎可以肯定,数组保证以零对齐方式打包。但是,几乎可以肯定。最好检查性病。
答案 3 :(得分:0)
我想在mah&的答案中添加一些内容。 quetzacoatl - 既有效又正确。
在您的示例中 - 如果需要打包,请添加编译指示,并确保即使编译器创建的布局与您预期的不同,副本也不会失败。如果编译器想要创建不同于所需的布局,请确保编译失败。