offset的模拟实现
题目要求
请你写一个宏,计算结构体某变量相对于首地址的偏移,并给出说明
宏的原型
解题思路
本题是让我们模拟offsetof这个宏的实现,所以当然我们不能直接套用原宏,需要我们手动实现。
我们观察可得,offsetof宏共有两个参数,分别是type (结构体类型),以及number(结构体中某变量的名称)
在做本题之前,我们应该掌握结构体的相关知识,其中最重要的就是内存对齐(面试常考),在这里我就不进行赘述,请同学们自行了解。
这道题难就难在,我们在不知道首地址的情况下,如何计算元素的偏移。
那么,突破点就在于此,既然我们不知道首地址,也就是说首地址不影响最终结果的大小,所以我们可以指定某个首地址,从而进行计算。
为了方便,我们可以将0处的地址就作为结构体首元素的地址。
首先,我们先定义一个宏,防止与原宏产生冲突,我们将其全部大写。
#define OFFSETOF(st_type, mem_name)
其中,st_type代表结构体的标签,mem_name代表结构体内的成员变量
所以,结构体首元素的地址可以表示成:
((st_type*)0)
那么,我们访问其中mem_name成员的地址,代码就可以写成:
&(((st_type*)0)->mem_name)
// 结构体中名为mem_name的变量相对于元素首地址(0位置处的地址)的偏移量
由于,原宏的返回值为size_t,所以为了和原宏保持一致,我们将地址强制类型转化为size_t,所以最终的代码如下
#define OFFSETOF(st_type, mem_name) (size_t)&(((st_type*)0)->mem_name)
测试数据
为了保险起见,我们可以对我们自己实现的宏进行一些测试:
int main()
{
/*printf("%d\n", offsetof(struct S, a));
printf("%d\n", offsetof(struct S, c));
printf("%d\n", offsetof(struct S, d));*/
printf("%d\n", OFFSETOF(struct S, a));
printf("%d\n", OFFSETOF(struct S, c));
printf("%d\n", OFFSETOF(struct S, d));
return 0;
}
编译的结果可知,我们自己实现的宏是正确的。
总结
我们今天讲解了一道有关offsetof宏实现的经典面试题,希望能给你带来一些帮助, 喜欢本期内容的话可以点赞 + 关注,谢谢大家。