我正在查看来自 的宏offsetof
,<cstddef>
并看到一个可能的实现是通过
#define my_offsetof(type, member) ((void*) &(((type*)nullptr)->member))
我试过了,确实可以按预期工作
#include <iostream>
#define my_offsetof(type, member) ((void*) &(((type*)nullptr)->member))
struct S
{
char x;
short y;
int z;
};
int main()
{
std::cout << my_offsetof(S, x) << '\n';
std::cout << my_offsetof(S, y) << '\n';
std::cout << my_offsetof(S, z) << '\n';
S s;
std::cout << (void*) &((&s)->x) << '\n'; // no more relative offsets
std::cout << (void*) &((&s)->y) << '\n'; // no more relative offsets
std::cout << (void*) &((&s)->z) << '\n'; // no more relative offsets
}
我所做的唯一修改是我使用最终转换为void*
而不是size_t
,因为我想将地址显示为指针。
我的问题:
- 代码是否完全合法,即通过 a “访问”成员是否合法
nullptr
,然后获取其地址?如果是这样,那么似乎&(((type*)nullptr)->member)
计算成员相对于0的地址,真的是这样吗?(似乎是这样,在最后 3 行中,我得到了相对于 的地址的偏移量s
)。 - 如果我
(void*)
从宏定义中删除最终转换为,我会得到一个段错误。为什么?不应该&(((type*)nullptr)->member)
是 type 的指针type*
,或者这里的类型是否被抹掉了?