簡體   English   中英

這是如何運作的? 將任何東西復制到一個字節數組(字符)

[英]How does this work? copying anything into an array of bytes (chars)

struct MyRect
{
    int x, y, cx, cy;
    char name[100];
};

int main()
{
    MyRect mr;
    mr.x = 100;
    mr.y = 150;
    mr.cx = 600;
    mr.cy = 50;
    strcpy(mr.name, "Rectangle1");

    MyRect* ptr;

    {
        unsigned char bytes[256];

        memcpy(bytes, &mr, 256);

        ptr = (MyRect*)bytes;
    }

    printf("X = %d\nY = %d\nCX = %d\nCY = %d\nNAME = %s\n", 
        ptr->x, ptr->y, ptr->cx, ptr->cy, ptr->name);

    return 0;
}

我只是在測試如何將一個struct /類放在一個字節數組中,並且在編譯和工作時很驚訝,printf打印出我在mr變量中設置的所有值。

只是有點困惑到什么“ptr”指向? 它在某處為ptr分配了內存嗎?

它純粹的機會。

首先,您基本上是對結構進行逐字節復制,並使用memcpy將其放入堆棧分配的緩沖區中。 但是,你不應該在實踐中這樣做。 這次碰巧工作了,因為你的結構是一個POD (普通舊數據或C結構),但如果你的結構是一個帶有構造函數/復制構造函數的C ++對象,或者你有什么東西,你可能會有一個討厭驚喜。

其次,包含結構的堆棧分配緩沖區在您通過指針使用時超出了范圍,因此您所做的是完全未定義的行為 它只能通過純粹的機會工作,並且不能保證在不同的計算機上或使用不同的編譯器,甚至在一天的不同時間再次工作。

好吧,你的程序會導致未定義的行為,所以你可能不會感到驚訝它恰好工作。 或者,如果它不能正常工作或導致宇宙結束,那么就是這樣。 在包含bytes定義的塊之后, ptr超出范圍,並且可能或可能仍未指向有效內存。 在你的情況下,它確實如此。 但你不能依賴這種行為。

unsigned char bytes[256]在堆棧上分配,即每次輸入函數(在本例中為main )時,堆棧上為變量bytes保留256 bytes 通過cast ptr現在指向堆棧上的這個區域並解釋為MyRect類型。 由於您首先將此類結構復制到堆棧區域,因此這一切都很好並且有效。 但是一旦你離開main ,區域ptr指向的區域就消失了,所以你可能不會在這個函數之外存儲指向該區域的指針。

ptr仍指向bytes地址。 或者,曾經被稱為bytes 即使你已經將bytes放入它自己的塊中,並且變量在該塊之外在語義上是不可訪問的,但是在函數退出之前,存儲器會保持不變。 這是一種典型的實現技術,但標准未定義,因此不依賴於它。

ptr = (MyRect*)bytes;

“bytes”是內存中數組的地址。

ptr在此代碼中分配了該地址。

演員告訴編譯器忽略數據類型的差異。

如果你詳細了解編譯器在幕后做了什么,這當然可以正常工作。 唯一的問題是更改編譯器或編譯器設置可能會導致此代碼失敗。 它可能有點脆弱。

它的工作原理是因為雖然'bytes'數組超出了范圍,但是當你調用printf()時,它所駐留的堆棧空間還沒有被踩到。 它也有效,因為雖然'mr'不是256字節大,但它后面的內存(在堆棧上)並不關心你是在讀它。

C是一種非常松散,非類型安全的語言。 指針可以指向任何內存位置,您可以轉換為您喜歡的任何指針類型。

所以我同意,你的程序基本上是偶然的。 但它確實如此,因為C允許用指針做一些瘋狂的事情。

暫無
暫無

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

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