为了加深对系统中,地址的含义的理解,对container_of进行了试验。不管代码怎么写,到最后,到机器执行的时候,所有的变量都会消失,都会变成地址:内存地址,寄存器地址。对于地址的解析,就是对包含的数据的信息的解析。
#include <stdio.h>
struct grid{
int index;
char *name;
float length;
};
#define moffsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define mcontainer_of(ptr,type,member) ({ \
const typeof( ((type *)0)->member ) *__mptr=(ptr); \
(type *)( (char *)__mptr-moffsetof(type,member));})
//顺便测试一下typeof
#define min(X,Y) \
({\
typeof(X) x=(X);\
typeof(Y) y=(Y);\
x>y?y:x;\
})
int main(){
//测试typeof
int m=6,n=8;
int l=min(m,n);
printf("min:%d\n",min(m++,n++));
double y;
typeof(y) x;
printf("x size:%d\n",sizeof(x));
struct grid *gd1=malloc(sizeof (struct grid));
char *anoname="name ok";
gd1->index=1;
gd1->length=8;
gd1->name=anoname;
unsigned long nameaddr=(unsigned long)&(gd1->name);
//gd1是一个指针变量,本身要占用4字节空间存储,有自己的地址空间
printf("gd1 addr:0x%x,gd1 point to 0x%x,name:%s, addr:%lx\n",&gd1,(unsigne d long)gd1,gd1->name,(unsigned long)&(gd1->name));
//gd2是一个指针变量,有自己的空间,
struct grid *gd2=(struct grid*)(nameaddr-4);
printf("gd2 addr:0x%x,point to addr 0x%x\n",&gd2,&(gd2->index));
printf("---after,index=%d,name=%s,length=%f\n",gd2->index,gd2->name,gd2->length);
printf("---after directly addr sub,index=%d,name=%s,length=%f\n",gd2->index,gd2->name,gd2->length);
//gd3又是一个指针变量,有自己的空间
struct grid *gd3 =mcontainer_of(&gd1->name,struct grid,name);
printf("gd3 addr 0x%x,point to addr:0x%x\n",&gd3,&(gd3->index));
printf("---after mcontainer_of,index=%d,name=%s,length=%f\n",gd3->index,gd3->name,gd3->length);
//正确的话,gd1,gd2,gd3这3个指针变量都要指向同一块内存空间,这个空间存放真实的数据
}
输出:‘
min:6
x size:8
gd1 addr:0xbfdace24,gd1 point to 0x9fe8008,name:name ok, addr:9fe800c
gd2 addr:0xbfdace20,point to addr 0x9fe8008
---after,index=1,name=name ok,length=8.000000
---after directly addr sub,index=1,name=name ok,length=8.000000
gd3 addr 0xbfdace1c,point to addr:0x9fe8008
---after mcontainer_of,index=1,name=name ok,length=8.000000
由此可以看到,对于地址进行适当的操作,可以很自由的做一些事情。