我有一个简单的结构,如下所示:
struct Object
{
int x_;
double y_;
};
我正在尝试操纵对象的原始数据,这就是我所做的:
int main()
{
Object my_object;
unsigned char* raw_data = reinterpret_cast<unsigned char*>(&my_object);
int x = 10;
memcpy(raw_data, &x, sizeof(x));
raw_data += sizeof(x);
double y = 20.1;
memcpy(raw_data, &y, sizeof(y));
Object* my_object_ptr = reinterpret_cast<Object *>(raw_data);
std::cout << *(my_object_ptr).x << std::endl; //prints 20 (expected 10)
std::cout << *(my_object_ptr).y << std::endl; //prints Rubbish (expected 20.1)
}
我期待上面的代码可以工作,,,
真正的问题是什么?这甚至可能吗?
答案 0 :(得分:2)
这可能是结构填充问题。如果你有double y_
作为第一个成员,你可能已经看到了你的期望。如果在数组中使用struct,编译器将使用额外的字节填充结构以使对齐正确。试试
#pragma pack(4)
在结构定义之前。
Visual Studio的#pragma pack
引用:http://msdn.microsoft.com/en-us/library/2e70t5y1.aspx默认情况下,您的结构被打包为8个字节,因此在x_
和y_
之间有一个4字节的填充。
阅读http://www.catb.org/esr/structure-packing/以真正了解正在发生的事情。
答案 1 :(得分:2)
您需要使用offsetof
macro。还有一些问题,最重要的是你修改了raw_data
指针,然后将修改后的值转换回Object*
指针,导致未定义的行为。我选择删除raw_data
修改(替代方法是不将其强制转换,而是直接检查my_object
)。这是一个固定的代码,在评论中有解释:
#include <iostream>
#include <cstring> // for memcpy
#include <cstddef> // for offsetof macro
struct Object
{
int x_;
double y_;
};
int main()
{
Object my_object;
unsigned char* raw_data = reinterpret_cast<unsigned char*>(&my_object);
int x = 10;
// 1st memcpy fixed to calculate offset of x_ (even though it is probably 0)
memcpy(raw_data + offsetof(Object, x_), &x, sizeof(x));
//raw_data += offsetof(Object, y_); // if used, add offset of y_ instead of sizeof x
double y = 20.1;
// 2nd memcpy fixed to calculate offset of y_ (offset could be 4 or 8, depends on packing, sizeof int, etc)
memcpy(raw_data + offsetof(Object, y_), &y, sizeof(y));
// cast back to Object* pointer
Object* my_object_ptr = reinterpret_cast<Object *>(raw_data);
std::cout << my_object_ptr->x_ << std::endl; //prints 10
std::cout << my_object_ptr->y_ << std::endl; //prints 20.1
}