1. 宏offsetof的作用
在www.cplusplus.com中对offsetof宏的功能描述:
这个宏的作用就是传入一个结构体类型和一个成员名,返回这个成员相对比这个结构体起始位置的偏移量(字节数),如果不懂的话可以看这篇文章:计算结构体的大小!结构体内存对齐的意义是什么?。
2. 分析该如何模拟实现
有这么一个结构体:
struct Test {
char c;
int a;
char* str;
};
根据结构体的内存对齐规则,得出它的大小与成员的内存布局如下(假设机器是64位平台):
那么如何得到c、a或str相对于起始位置的偏移量呢?其实非常简单,比如想要得到c的偏移量,用c、a或str的地址减去这个结构体的起始位置,得到的就是中间相差的字节数,这个字节数也就相当于相对于起始位置的偏移量了。
3.模拟实现
#include <stdio.h>
#include <stddef.h>
// 模拟实现offsetof宏
#define OFFSETOF(type, member) (size_t)(&(((type*)0)->member))
struct Test {
char c;
int a;
char* str;
};
int main() {
printf("%zd ", offsetof(struct Test, c));
printf("%zd ", offsetof(struct Test, a));
printf("%zd\n", offsetof(struct Test, str));
printf("%zd ", OFFSETOF(struct Test, c));
printf("%zd ", OFFSETOF(struct Test, a));
printf("%zd\n", OFFSETOF(struct Test, str));
return 0;
}
运行结果对比:
&(((type*)0)->member)
我认为在0的位置处有一个type*的结构体,然后将它的成员地址取出,这个成员的起始地址就是相对于结构体起始位置的偏移量了,因为结构体的起始位置我认为是0,成员地址减去0的地址等于不用减。一般而言,0这种地址是不能使用的,但我这里并没有解引用,只是看看但不用是没有问题的。