offsetof

16.offsetof宏
#define offsetof(TYPE,MEMBER) ((int) &((TYPE *)0)-> MEMBER)
上式是offsetof的定义式,其中TYPE是结构体变量类型,MEMBER是结构体中的成员,返回的是该成员的地址相对结构体首地址的偏移量。
offsetof宏的原理:我们虚拟一个type类型结构体变量,然后用type.member的方式来访问哪个member元素,继而得到member相对整个变量首地址的偏移量。
解析((int) &((TYPE *)0)-> MEMBER):
(TYPE *)0:将地址0强制类型转化为指向TYPE类型的指针,可以记为p = (TYPE *)0;p是指向TYPE类型的指针,它的值为0;
((TYPE *)0)-> MEMBER:->的优先级高一些,将该指针指向结构体中的MEMBER成员;
&((TYPE *)0)-> MEMBER):对该成员取地址;该值即为MEMBER成员的偏移量,因为该结构体类型的首地址为0.
((int) &((TYPE *)0)-> MEMBER):将该地址转换成int,
offsetof中的亮点就是将该结构体的首地址强制为0.
struct mystruct
{
char a;
int b;
short c;
};


#define offsetof(TYPE,MEMBER) ((int) &((TYPE *)0)-> MEMBER)


int main(void)
{
int offseta = (int)offsetof(struct mystruct, a);
printf("offseta = %d.\n", offseta);
int offsetb = (int)offsetof(struct mystruct, b);
printf("offseta = %d.\n", offsetb);
int offsetc = (int)offsetof(struct mystruct, c);
printf("offsetc = %d.\n", offsetc);
}


/****************************************************************/


当然,在我们定义简单的结构体变量的时候,我们是可以直接通过转换来计算偏移量的,方法如下:
struct mystruct
{
char a; // 0
int b; // 4
short c; // 8
};
int main(void)
{
printf("整个结构体变量的首地址:%p.\n", &s1); //&s1取结构体首地址
printf("s1.b的首地址:%p.\n", &(s1.b)); //&(s1.b)取b成员地址
printf("偏移量是:%d.\n", (char *)&(s1.b) - (char *)&s1); //b对整个结构体的偏移量
}


/****************************************************************/
我们也可以先让一个指针指向该结构体的首地址,然后将该指针移动适当的偏移量,然后解引用移动后的指针来获取对应成员的值。
struct mystruct
{
char a; // 0
int b; // 4
short c; // 8
};


int main(void)
{
struct mystruct s1;
s1.b = 12;

int *p = (int *)((char *)&s1 + 4); //&s1,结构体的首地址,(char *)&s1转为字符形式指针,然后指针走4个偏移
printf("*p = %d.\n", *p);


}

猜你喜欢

转载自blog.csdn.net/qq_20725221/article/details/51476465
今日推荐