memcpy的pod结构数组到数组

时间:2013-07-01 10:31:34

标签: c++

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的布局强制执行任何操作,因此我必须使用静态断言来确保它,对吗?

4 个答案:

答案 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 - 既有效又正确。

  1. 以不依赖于未定义的东西的方式编写代码。在这里,您的代码可能有效 - 因为double是8字节对齐并且通常是打包的。这仍然隐含着。你应该确保它始终使用POD的大小。
  2. 如果您需要打包,请通过添加pragma pack或类似内容将其显式化。它在代码中声明了您的要求。
  3. 如果代码不符合您的要求,请确保代码失败。如果可能,请使用static_assert,如果不能使用断言,错误处理代码和/或单元测试。
  4. 在您的示例中 - 如果需要打包,请添加编译指示,并确保即使编译器创建的布局与您预期的不同,副本也不会失败。如果编译器想要创建不同于所需的布局,请确保编译失败。

相关问题