【发布时间】:2022-01-10 08:05:27
【问题描述】:
给定以下结构:
// sizeof == 8
struct Data {
int Foo;
int Bar;
};
// sizeof == 16
struct __declspec(align(8)) Consumer {
char Padder00[4];
char Padder01[4];
Data* Data;
};
我希望 Data* 等于一个数字,跨越 8 个字节(就像我在 x64 上一样),这是 Data 类型结构的起始地址。
现在,调试以下示例:
int main()
{
Consumer consumer;
consumer.Data = (Data*)malloc(sizeof(Data));
// consumer.Data == 0x0000013c86eb1300
// &consumer.Data == 0x00000037cdcff660
consumer.Data->Bar = 1337;
consumer.Data->Foo = 42069;
char* stepper = (char*)(&consumer);
stepper += 4; // skipping 1st padder
stepper += 4; // skipping 2nd padder
Data* restored = ((Data*)stepper);
// restored == 0x00000037cdcff660
// == &consumer.Data
free(consumer.Data);
std::getchar();
return 0;
}
所以restored == &consumer.Data 而我本来希望它是restored == consumer.Data,更进一步并查看stepper 的每个字节会产生以下结果:
stepper[0] = 0x00
stepper[1] = 0x13
stepper[2] = 0xeb
stepper[3] = 0x86
stepper[4] = 0x3c
stepper[5] = 0x01
stepper[6] = 0x00
stepper[7] = 0x00
// 0x0000013c86eb1300 (little endian)
// 0x0000013c86eb1300 == consumer.Data
总结:
((Data*)stepper) == &consumer.Data == (*(Data**)stepper)
我希望它在哪里
((Data*)stepper) == consumer.Data
那么……这里到底发生了什么巫术?
【问题讨论】:
-
你为什么期待别的?
stepper首先指向Consumer对象的开头,然后通过添加整数逐步遍历该对象。最后你仍然指向Consumer对象,别无他处。使用转换(Data*)stepper的结果会导致未定义的行为,因为在stepper指向的位置没有Data对象。那里只有一个Data*。 -
您的预期不正确。
stepper是指针consumer.Data的地址,而不是它的值。所以你看到的是((Data*)stepper) == &consumer.Data。 -
做同样的事情,但使用
int而不是Data*- 您是否期望(int) stepper是int的值? (指针没有什么特别之处。) -
@molbdnilo 谢谢!这很清楚。我想我只是想多了。