简体   繁体   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;
}

I was just testing how to put a struct/class in an array of bytes, and was suprised when it compiled and worked, the printf prints all the values which i set in the mr variable. 我只是在测试如何将一个struct /类放在一个字节数组中,并且在编译和工作时很惊讶,printf打印出我在mr变量中设置的所有值。

just a little confused to what exactly "ptr" is pointing to? 只是有点困惑到什么“ptr”指向? has it allocated memory for ptr somewhere? 它在某处为ptr分配了内存吗?

It works by pure chance. 它纯粹的机会。

Firstly, you're basically making a byte-by-byte copy of the struct and placing it in a stack-allocated buffer using memcpy . 首先,您基本上是对结构进行逐字节复制,并使用memcpy将其放入堆栈分配的缓冲区中。 However, you shouldn't do this in practice. 但是,你不应该在实践中这样做。 It happened to work this time, because your struct is a POD (plain-old-data or C-struct), but if your struct was a C++ object with constructors/copy-constructors or what have you, you may have gotten a nasty surprise. 这次碰巧工作了,因为你的结构是一个POD (普通旧数据或C结构),但如果你的结构是一个带有构造函数/复制构造函数的C ++对象,或者你有什么东西,你可能会有一个讨厌惊喜。

Secondly, the stack-allocated buffer containing the struct goes out of scope by the time you use it via your pointer, so what you're doing is totally undefined behavior . 其次,包含结构的堆栈分配缓冲区在您通过指针使用时超出了范围,因此您所做的是完全未定义的行为 It only works by pure chance, and is not guaranteed to work again on a different computer or with a different compiler, or even at a different time of day. 它只能通过纯粹的机会工作,并且不能保证在不同的计算机上或使用不同的编译器,甚至在一天的不同时间再次工作。

Well, your program causes undefined behaviour, so you should probably not be surprised that it happens to work. 好吧,你的程序会导致未定义的行为,所以你可能不会感到惊讶它恰好工作。 Or if it happened to not work or caused the universe to end, for that matter. 或者,如果它不能正常工作或导致宇宙结束,那么就是这样。 After your block containing the definition of bytes , ptr is out of scope, and may or may not still point to valid memory. 在包含bytes定义的块之后, ptr超出范围,并且可能或可能仍未指向有效内存。 In your case, it does. 在你的情况下,它确实如此。 But you can't rely on that behaviour. 但你不能依赖这种行为。

The unsigned char bytes[256] are allocated on the stack, ie everytime your function (in this case main ) is entered, 256 byte are reserved on the stack for the variable bytes . unsigned char bytes[256]在堆栈上分配,即每次输入函数(在本例中为main )时,堆栈上为变量bytes保留256 bytes And through the cast ptr is now pointing to this area on the stack and interpreted as being of type MyRect . 通过cast ptr现在指向堆栈上的这个区域并解释为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. 但是一旦你离开main ,区域ptr指向的区域就消失了,所以你可能不会在这个函数之外存储指向该区域的指针。

ptr is still pointing to the address of bytes . ptr仍指向bytes地址。 Or, what was once called bytes . 或者,曾经被称为bytes Even though you've put bytes into its own block and the variable is semantically inaccessible outside of that block, the memory sticks around unmodified until the function exits. 即使你已经将bytes放入它自己的块中,并且变量在该块之外在语义上是不可访问的,但是在函数退出之前,存储器会保持不变。 This is a typical implementation technique, but is undefined by the standard, so don't depend on it. 这是一种典型的实现技术,但标准未定义,因此不依赖于它。

ptr = (MyRect*)bytes;

"bytes" is the address of the array in memory. “bytes”是内存中数组的地址。

ptr gets assigned that address in this code. ptr在此代码中分配了该地址。

The cast tells the compiler to ignore the difference in data types. 演员告诉编译器忽略数据类型的差异。

If you understand in detail what the compiler is doing under the covers this can certainly work just fine. 如果你详细了解编译器在幕后做了什么,这当然可以正常工作。 The only problem is changing compilers or compiler settings might cause this code to fail. 唯一的问题是更改编译器或编译器设置可能会导致此代码失败。 It can be a bit fragile. 它可能有点脆弱。

It works because though the 'bytes' array is out of scope, the stack space it resides in is has not been stepped on by the time you call printf(). 它的工作原理是因为虽然'bytes'数组超出了范围,但是当你调用printf()时,它所驻留的堆栈空间还没有被踩到。 It also works because though 'mr' is not 256 bytes large, the memory following it (on the stack) doesn't care that you are reading it. 它也有效,因为虽然'mr'不是256字节大,但它后面的内存(在堆栈上)并不关心你是在读它。

C is a very loose, non-type-safe language. C是一种非常松散,非类型安全的语言。 Pointers can point to just about any memory location and you can cast to any pointer type you like. 指针可以指向任何内存位置,您可以转换为您喜欢的任何指针类型。

So I agree, your program basically works by accident. 所以我同意,你的程序基本上是偶然的。 But it does so, because C permits some wild things to be done with pointers. 但它确实如此,因为C允许用指针做一些疯狂的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM