一,offsetof宏
1,作用:计算结构体中某个元素与结构体首地址的偏移量。
2,原理:虚拟一个0地址处的结构体类型变量type,然后用type.member的方式来访问那个member元素,继而得到member相对于整个变量首地址的偏移量。
3,自己实现:offsetof(type,member) ( (unsigned long) &((type *)0)->member )
4,分布分析:(type *)0 将地址0强制转换为一个结构体类型变量,((type *)0)->member 指向结构体变量的成员,&((type *)0)->member 得到这个成员变量的地址,这个地址是从0地址开始的,故而便是这个成员变量相对于结构体首地址的偏移量。
二,container_of宏
1,作用:知道一个结构体中某个成员变量的指针,来反推这个结构体的指针。使得可以从一个成员变量的指针得到整个结构体的指针,继而得到结构体中其他元素的指针。
2,typeof关键字的作用是:typeof(a)由变量a得到a的类型,由变量名得到变量的数据类型。
3,实现:
#define container_of(ptr,type,member) ({ \
const typeof(((type *)0)->member) *mptr = (ptr);\
(type *)((unsigned long)mptr - offsetof(type, member));\
})
4,原理:先用typeof得到member元素的类型,然后定义成一个这个类型的指针,然后用这个指针减去该元素相对于整个结构体的偏移量(用offsetof宏得到),减去之后得到的就是整个结构体变量的首地址了,再把这个地址强制类型转换为type *就是结构体变量的指针了。
#include<stdio.h>
#pragma pack(4)
#define offsetof(type,member) ((unsigned long)&((type *)0)->member)
#define container_of(ptr,type,member) ({const typeof(((type *)0)->member) *mptr = (ptr);\
(type *)((unsigned long)mptr - offsetof(type, member));})
typedef struct Mystruct1
{ // 1字节 4字节 8字节
int a; // 4 4 4
char b; // 1 1+1 1+1
short c; // 2 2 2
}S1;
typedef struct Mystruct5{
char a; // 1+3 1+3
S1 s1; // 8 8
double b; // 8 8
int c; // 4 4+8
}S5;
int main()
{
int off;
off = offsetof(S1,c);
printf(" off = %d \n",off); //6
off = offsetof(S5,b);
printf(" off = %d \n",off); //12
S5 s5;
S5 *p = NULL;
printf(" s5 = %p \n",&s5); //0x7ffc5c373c70
p = container_of(&s5.b,S5,b);
printf(" p = %p \n",p); //0x7ffc5c373c70
}
#pragma pack()
所有评论(0)