【发布时间】:2014-06-16 06:25:54
【问题描述】:
我正在包装一个脚本库,并且这个宏存在。
#define asOFFSET(s,m) ((size_t)(&reinterpret_cast<s*>(100000)->m)-100000)
m 是什么类型?它有例子:
struct MyStruct
{
int a;
};
asOFFSET(MyStruct,a)
我想把它放到一个函数中。
【问题讨论】:
我正在包装一个脚本库,并且这个宏存在。
#define asOFFSET(s,m) ((size_t)(&reinterpret_cast<s*>(100000)->m)-100000)
m 是什么类型?它有例子:
struct MyStruct
{
int a;
};
asOFFSET(MyStruct,a)
我想把它放到一个函数中。
【问题讨论】:
脚本库(最有可能)使用宏来找出类成员的内部布局,而无需对其类型、体系结构或继承模型进行假设。 (一个简单的例子是discussed here)。
对于大多数 C++ 程序,理想情况下根本不需要这些信息(内存布局)。但是如果您确实需要它(例如,如果您正在编写分析器/调试器),您最好按原样保留这个宏(或者最好用 offsetof 替换它在代码中的用法,就像 Michael Anderson指出。)有compiler-specific implementations是
使用这些等效选项,理想情况下应该不需要手纺替代品或包装纸。
【讨论】:
这是offsetof 宏的实现。 m 是 s 的任何成员。它没有对应的 C 或 C++ 类型 - 但与 pointer to member 的概念密切相关。
【讨论】:
offsetof 根据定义没有。
宏的目的是确定,给定结构的any名称和该结构的成员的any名称,在内存中的距离 从结构的任意实例的开头,以及该成员在同一实例中的位置。
m 没有“类型”,s 也没有。 当您使用宏时,“类型”的整个概念就会消失。这东西简直不是C++;它基本上是一种完全独立的语言,用于就地编辑 C++ 代码。当预处理器运行时,asOFFSET(MyStruct, a) 将在编译器开始工作之前被文本替换 ((size_t)(&reinterpret_cast<MyStruct*>(100000)->a)-100000)。
((size_t)(&reinterpret_cast<MyStruct*>(100000)->a)-100000) 旨在评估为 0,因为 MyStruct 实例的 a 成员出现在每个实例的开头。我实际上并不是 100% 确定这是符合规范的合法行为,但意图如下:
通过将数字100000 视为指向MyStruct 的指针,假设在内存位置100000 存在MyStruct 的实例。
获取这个假结构的a成员在内存中的地址,然后再次减去100000。这给了我们从假结构的开头到该假结构的指定成员的距离。
将该数值转换回size_t(用于测量内存分配的数值类型,无符号整数类型)。
【讨论】:
struct MyStruct {/*int fake1;*/ long fake2; int a;}; `printf("%d\n",(int)asOFFSET(MyStruct,a));` 的结果将是8。如果结构为:struct MyStruct {int fake1; long fake2; int a;};,则结果将为16。为什么?