英文:
What is the meaning of operation in c
问题
我正在尝试序列化PHP的操作码。我对这段代码感到困惑。请检查以下代码。这段代码的含义是什么。
(ptr) = (void*)((char*)(ptr) - (char*)script->mem)
如何序列化op_array
?
英文:
I am trying to serialize PHP opcode. I am confused with code. Please check following code. What is the meaning of the code.
(ptr) = (void*)((char*)(ptr) - (char*)script->mem)
How to serialize op_array
?
答案1
得分: 7
这是一个老的游戏编程技巧,用于将指针序列化/反序列化到磁盘。
有点不太规范,但让我尽量解释一下。以一个极为简化的示例为例,假设我有以下结构体:
struct FileContents
{
char text[10] = {0,1,2,3,4,5,6,7,8,9};
char* ptr = text + 5; //< 指向第5个元素
};
我想使用fread/fwrite一次性读取/写入该结构体。如果我简单地这样做:
void writeFile(FileContents contents)
{
FILE* fp = fopen("blah.dat", "wb");
fwrite(&contents, sizeof(FileContents), 1, fp);
fclose(fp);
}
这对于contents.text中存储的值将正常工作,但对于contents.ptr会出现严重问题(因为此指针引用内存地址,如果我们想再次读取数据,很难重新获取相同的内存位置)。
因此,我们需要对所有指针值进行修复/还原操作。我们可以通过以下方式实现:
struct FileContents
{
char text[10] = {0,1,2,3,4,5,6,7,8,9};
void* ptr = (text + 5); //< 指向第5个元素
// 将 'ptr' 转换为相对于结构体开头的整数偏移量
void unfix()
{
// 这是我们将要写入文件的第一个字节
char* startOfFile = (char*)this;
// 这是有问题的指针值。
char* ptrValue = ptr;
// 现在,让我们计算从结构体开头到指针指向的内存位置的字节偏移量...
// (在这种情况下,偏移量将为5)
size_t offset = ptrValue - startOfFile;
// 现在,让我们修改ptr的值,使其现在存储一个字节偏移量,而不是内存位置。
// (我们需要将偏移量强制转换为指针值,否则这不会起作用)
ptr = (void*)offset;
}
// 读取文件后(反序列化),我们需要将该整数偏移量重新转换为有效的内存地址...
void refix()
{
// 获取内存中结构体的起始位置
char* startOfFile = (char*)this;
// 并将偏移量添加到文件的起始位置,以获取有效的内存位置
ptr = startOfFile + ((size_t)ptr);
}
};
英文:
So, this is an old game coders trick, intended to serialise/deserialise a pointer to/from disk.
It's a little dirty, but lets see if I can explain somehow. Using a vastly oversimplified example, lets imagine I have this struct:
struct FileContents
{
char text[10] = {0,1,2,3,4,5,6,7,8,9};
char* ptr = text + 5; //< point to element 5
};
and I want to read/write that struct using fread/fwrite in one go. If i was to simply do:
void writeFile(FileContents contents)
{
FILE* fp = fopen("blah.dat", "wb");
fwrite(&contents, sizeof(FileContents), 1, fp);
fclose(fp);
}
This would work fine for the values stored in contents.text, but would horribly fail for contents.ptr (since this pointer is referring to a memory address, and it's unlikely we will be able to re-claim that same memory location if we wanted to read the data again).
As such, we need an unfix/refix operation on all the pointer values. We can achieve this by doing:
struct FileContents
{
char text[10] = {0,1,2,3,4,5,6,7,8,9};
void* ptr = (text + 5); //< point to element 5
// convert 'ptr' to be an integer offset from the start of the struct
void unfix()
{
// heres the first byte we will write to the file
char* startOfFile = (char*)this;
// here's the problematic pointer value.
char* ptrValue = ptr;
// now lets compute a byte offset from the start of the struct,
// to the memory location ptr is pointing to...
// (in this case, the offset will be 5)
size_t offset = ptrValue - startOfFile;
// now lets modify the value of ptr so that it now stores a byte
// offset, rather than a memory location. (We need to cast the
// offset to a pointer value, otherwise this wont work)
ptr = (void*)offset;
}
// AFTER reading the file (deserialise), we need to convert
// that integer offset back into a valid memory address...
void refix()
{
// grab start of struct in memory
char* startOfFile = (char*)this;
// and add the offset to the start of the file, to
// get the valid memory location
ptr = startOfFile + ((size_t)ptr);
}
};
答案2
得分: 2
似乎您有一个 void* ptr
和 sometype* script->mem
,您将它们都转换为 char*
并相互减去,然后将结果转换为 void*
。
英文:
it seems that you have a void* ptr
and sometype* script->mem
, you cast them both to char*
and subtract one from another, then you cast the result to void*
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论