memcpy是否保留不同类型之间的数据? [英] Does memcpy preserve data between different types?

查看:554
本文介绍了memcpy是否保留不同类型之间的数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果缓冲区大小足够,在两个不同的结构上调用memcpy是否保留原始数据?如果它们各自的数据类型重叠,是否定义为使用先前数据类型的数据检索另一数据类型的值?

Does calling memcpy on two different structures preserve the original data if the buffer size is sufficient? And is it defined to retrieve values of another data type with data of previous data type if their respective data types overlap?

这两种c/cpp语言都应该类似,但是我在cpp中提供了一个示例-

This should be similar for both c/cpp languages but I'm providing an example in cpp -

#include <iostream>
#include <cstring>

using namespace std;

struct A{
  int a;
  char b[10];
};

struct B{
  int ba;
  int bb;
};

int main(){
    B tmp;
    tmp.ba = 50;
    tmp.bb = 24;
    cout << tmp.ba << tmp.bb << "\n";

    // everything is fine yet

    A obj;
    memcpy(&obj, &tmp, sizeof(tmp));

    // 1. is this valid?
    cout << obj.a << "\n";

    B newB;
    memcpy(&newB, &obj, sizeof(newB));

    // 2. Are these valid?
    cout << newB.ba << newB.bb << "\n";
}

在上面的示例中,我评论了第一条评论和第二条评论,如果提供了足够的缓冲区,它们是否有效?是否保留了数据?我们可以方便地做到这一点吗?

In above example I've commented 1st and 2nd comment, are they valid and is data preserved if sufficient buffer area is provided? Can we do this portably?

结构和与之相关的其他功能在C库中,但我们将使用c ++对其进行编译.

The structure and other functions related to it are in C library but we'll use and compile it with c++.

推荐答案

除了遵循C标准外,C ++标准未指定memcpy的行为. (也许避免解决此类问题!).在C标准中,它被定义为等同于一系列字符类型副本 1 .

The C++ Standard doesn't specify the behaviour of memcpy, other than deferring to the C Standard. (Perhaps to avoid tackling issues like this!). In the C Standard it's defined as being equivalent to a sequence of character type copies1.

因此将memcpy(&obj, &tmp, sizeof(tmp));视为:

unsigned char *dst = (char *)&obj;
unsigned char *src = (char *)&tmp;
for (size_t i = 0; i != sizeof tmp; ++i)
    dst[i] = src[i];

,然后使用C ++标准来覆盖该代码.

and then use the C++ Standard to cover that code.

现在的问题是:

  1. &tmp&obj确实给出了对象开始的地址吗?
  2. obj中填充字节怎么办?
  3. tmp中的未初始化填充字节怎么办?
  4. obj的子对象的值会发生什么?
  1. Does &tmp, &obj actually give the address of the start of the object?
  2. What about padding bytes in obj?
  3. What about uninitialized padding bytes in tmp?
  4. What happens to the values of sub-objects of obj?

问题1:是的,由于没有基类子对象(并且不会重载operator&),因此[class.mem]/19对此进行了介绍.

Issue 1: Yes, this is covered by [class.mem]/19, since there are no base class subobjects (and it doesn't overload operator&).

问题2:我找不到任何专门介绍此内容的文字;但是如果不允许写填充字节,则将类类型对象复制到char缓冲区然后再返回到对象的标准中的示例将无法正常工作.

Issue 2: I cannot find any text specifically covering this; but the example in the standard of copying a class-type object into a char buffer and back into the object, would not work if it were not permitted to write padding bytes.

问题3:在[dcl.init]/12中有一些文本明确允许将上述代码用于未初始化的数据;并且目标将包含不确定的值.因此,如果仅将源中未初始化的填充字节映射到目标中未初始化的填充字节,就可以了.但是,如果将它们映射到目标中的子对象,则这些对象将具有不确定的值.

Issue 3: In [dcl.init]/12 is some text that explicitly permits the use of the above code for uninitialized data; and the destination will contain indeterminate values. So if uninitialized padding bytes in the source are only mapped to uninitialized padding bytes in the destination, it's fine. But if they are mapped to sub-objects in the destination, then those objects will have indeterminate value.

问题4:这里没有问题,严格的别名规则允许对象通过字符类型表达式覆盖其部分(或全部)字节.稍后访问该对象将产生与表示形式相对应的值,如果它不表示值,则使用UB.

Issue 4: There's no problem here, the strict aliasing rule permits objects to have some (or all) of their bytes overwritten through a character type expression. Accessing the object later will yield the value corresponding to the representation, with UB if it doesn't represent a value.

总而言之,假设sizeof(A) >= sizeof(B),我认为您的示例很好.

So, all in all, I think your specific example is OK, assuming sizeof(A) >= sizeof(B).

1 在C语言中,memcpy还保留对象的有效类型. C ++具有不同的对象模型,没有与此等效的对象模型.因此,如果您在C编译器中使用了类似的代码,则还需要遵守两个对象中类型之间的严格别名规则.

1 In C, memcpy also preserves the effective type of the object. C++ has a different object model and there is no equivalent of this. So if you used similar code with a C compiler, you'd also need to observe the strict aliasing rule between the types in both objects.

这篇关于memcpy是否保留不同类型之间的数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆