簡體   English   中英

memcpy是否在不同類型之間保留數據?

[英]Does memcpy preserve data between different types?

如果緩沖區大小足夠,在兩個不同的結構上調用memcpy是否會保留原始數據? 是否定義了如果其各自的數據類型重疊,則使用先前數據類型的數據檢索另一種數據類型的值?

對於c / cpp語言,這應該是類似的,但我在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";
}

在上面的例子中,我評論了第一和第二條評論,如果提供了足夠的緩沖區,它們是否有效並保留數據? 我們可以這么便攜嗎?

與它相關的結構和其他函數在C庫中,但我們將使用c ++編譯它。

除了推遲到C標准之外,C ++標准沒有指定memcpy的行為。 (也許是為了避免解決這樣的問題!)。 在C標准中,它被定義為等同於一系列字符類型副本1

因此處理memcpy(&obj, &tmp, sizeof(tmp));似乎是合理的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 ++標准來覆蓋該代碼。

現在的問題是:

  1. &tmp&obj實際上是否給出了對象開頭的地址?
  2. obj填充字節怎么樣?
  3. tmp未初始化的填充字節怎么樣?
  4. obj的子對象的值會發生什么變化?

問題1:是的,這由[class.mem] / 19涵蓋,因為沒有基類子對象(並且它不會重載operator& )。

問題2:我找不到任何具體涉及此事的文字; 但是,如果不允許寫入填充字節,則將類型對象復制到char緩沖區並返回到對象的標准中的示例將不起作用。

問題3:在[dcl.init] / 12中有一些文本明確允許將上述代碼用於未初始化的數據; 目的地將包含不確定的值。 因此,如果源中未初始化的填充字節僅映射到目標中未初始化的填充字節,那就沒問題。 但是如果它們映射到目標中的子對象,那么這些對象將具有不確定的值。

問題4:這里沒有問題,嚴格別名規則允許對象通過字符類型表達式覆蓋其中一些(或全部)字節。 稍后訪問該對象將產生對應於該表示的值,如果它不表示值,則使用UB。

所以,總而言之,我認為你的具體例子是可以的,假設sizeof(A) >= sizeof(B)


1在C中,memcpy還保留了對象的有效類型 C ++有一個不同的對象模型,沒有相應的。 因此,如果您使用與C編譯器類似的代碼,則還需要遵守兩個對象中類型之間的嚴格別名規則。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM