我期待在宏观offsetof的<cstddef>,看到一个可能的实现是通过
#define my_offsetof(type, member) ((void*) &(((type*)nullptr)->member))
Run Code Online (Sandbox Code Playgroud)
我尝试过它确实按预期工作
#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
}
Run Code Online (Sandbox Code Playgroud)
我做过的唯一修改是使用最终的强制转换void*而不是size_t,因为我想将地址显示为指针.
我的问题:
nullptr,然后获取其地址?如果是这种情况,那么似乎&(((type*)nullptr)->member)计算成员的地址相对于0,这是否确实如此?(看起来如此,就像在最后3行中我得到相对于地址的偏移量s).(void*)从宏定义中删除最终的强制转换,我会得到一个段错误.为什么?不&(((type*)nullptr)->member)应该是类型的指针type*,或者这种类型以某种方式擦除?
- 代码完全合法吗?
不,这是未定义的行为.编译器可以选择以offsetof这种方式实现,但那是因为它是实现:它可以选择如何实现自己的功能.另一方面,你不会得到这样的"奢侈品".
您无法实现offsetof宏.不符合任何标准的方式.
- 如果我从宏定义中删除最终的强制转换为(void*),我会得到一个段错误.为什么?不应该&(((类型*)nullptr) - >成员)是类型*的指针,或者这里以某种方式删除的类型?
这可能是从尝试打印段错误my_offsetof(S, x)(因为x是char和表达式的结果char*),因为std::ostream的operator<<将尝试打印char*作为一个C风格的字符串.
| 归档时间: |
|
| 查看次数: |
411 次 |
| 最近记录: |