2
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;
}

我只是在测试如何将一个结构/类放入一个字节数组中,并且在它编译和工作时感到惊讶,printf 打印了我在 mr 变量中设置的所有值。

对“ptr”到底指的是什么有点困惑?它是否在某处为 ptr 分配了内存?

4

6 回答 6

9

它纯属偶然。

首先,您基本上是在制作结构的逐字节副本,并使用memcpy. 但是,您不应该在实践中这样做。这次它碰巧起作用了,因为你的结构是一个POD(plain-old-data 或 C-struct),但如果你的结构是一个带有构造函数/复制构造函数的 C++ 对象,或者你有什么,你可能会遇到麻烦惊喜。

其次,当您通过指针使用它时,包含该结构的堆栈分配缓冲区超出范围,因此您所做的是完全未定义的行为。它只能在纯属偶然的情况下工作,不能保证在不同的计算机或不同的编译器上,甚至在一天中的不同时间再次工作。

于 2010-09-22T18:14:28.697 回答
2

好吧,您的程序会导致未定义的行为,因此您可能不会对它碰巧起作用感到惊讶。或者如果它碰巧不起作用或导致宇宙终结,就此而言。在包含 , 定义的块之后bytesptr超出范围,并且可能仍指向有效内存,也可能不指向有效内存。在你的情况下,确实如此。但是你不能依赖这种行为。

于 2010-09-22T18:13:56.560 回答
2

The unsigned char bytes[256] are allocated on the stack, i.e. everytime your function (in this case main) is entered, 256 byte are reserved on the stack for the variable bytes. And through the cast ptr is now pointing to this area on the stack and interpreted as being of type MyRect. Since you first copied such a struct to the stack area this is all fine and valid. But as soon as you leave main, the area ptr points to is gone, so you may not store a pointer to that area outside of this function.

于 2010-09-22T18:15:51.190 回答
1

ptr仍然指向 的地址bytes。或者,曾经被称为bytes. 即使您已将其放入bytes自己的块中,并且该变量在该块之外在语义上是不可访问的,但在函数退出之前,内存仍保持不变。这是一种典型的实现技术,但没有被标准定义,所以不要依赖它。

于 2010-09-22T18:18:23.667 回答
0
ptr = (MyRect*)bytes;

"bytes" is the address of the array in memory.

ptr gets assigned that address in this code.

The cast tells the compiler to ignore the difference in data types.

如果您详细了解编译器在幕后所做的事情,这当然可以正常工作。唯一的问题是更改编译器或编译器设置可能会导致此代码失败。它可能有点脆弱。

于 2010-09-22T18:17:48.237 回答
0

它之所以有效,是因为尽管“字节”数组超出了范围,但在您调用 printf() 时,它所在的堆栈空间还没有被踩到。它也可以工作,因为虽然 'mr' 不是 256 字节大,但它后面的内存(在堆栈上)并不关心你正在阅读它。

C 是一种非常松散的、非类型安全的语言。指针可以指向几乎任何内存位置,并且您可以转换为您喜欢的任何指针类型。

所以我同意,你的程序基本上是偶然的。但它确实这样做了,因为 C 允许使用指针来完成一些疯狂的事情。

于 2010-09-22T18:27:03.340 回答