1·由结构体指针进而访问各元素的原理—结构体首地址+元素偏移量
2· offsetof宏的作用:用宏来计算结构体某个元素和结构体首地址的偏移量(其实是通过编译器帮外面计算偏移量)
2·1 offsetof宏的原理:可以虚拟一个type类型的结构体变量,然后用type.member的方式来访问那个member元素,继而得到member相对于整个变量首地址的偏移量。
#define offsetof(TYPE,MEMBER) ((int) &((TYPE * ) 0 ) -> MEMBER)
(TYPE *) 0
这是一个强制类型转换,把0地址强制类型转换成一个指针,这个指针指向一个TYPE类型的结构体变量。(实际上这个结构体变量可能不存在,但是只要我不去解引用这个指针就不会出错)
( (TYPE *) 0 ) -> MEMBER
(TYPE *) 0 表示一个TYPE类型的结构体指针,通过这个指针来访问这个结构体变量的member元素。
& ( (TYPE *) 0 ) -> MEMBER
等效于 & (( (TYPE *) 0 ) -> MEMBER),意义是得到member元素的地址。但是因为整个元素结构体变量的首地址是0.
#include <stdio.h>
struct mystruct
{
char a;
int b;
short c;
};
#define offsetof(TYPE,MEMBER) ((int) ((TYPE * ) 0 ) -> MEMBER)
int main (void)
{
struct mystruct s1;
s1.b = 133;
printf("s1.b = %d\n",s1.b);
// 这个方法是用指针来访问结构体
int *p = (int *)((int *)&s1 + 4);//这里+4 是因为结构体对齐访问。
printf("*p = %d\n",*p);
return 0;
}
3· container_of宏
#define container_of(ptr,type,member)({
const typeof(((type *) 0 -> member) * __mptr = (ptr);
(type *) (char *) __mptr offsetof(type,member)); })
作用:知道一个结构体中某个元素的指针,反推整个结构体变量的指针,继而得到结构体变量中其他元素的指针。