上次在操作结构体地址的时候,本来想取结构体第二个成员变量的地址,就在第一个成员变量基址上增加了第一个成员变量的大小,但是发现结果不对
struct student查看一下结构体的地址
{
int a;
int b;
double c;
};
printf("stu size %d\n",sizeof(stu));结果如下:
printf("stu.a address %x\n",&stu.a);
printf("stu.b address %x\n",&stu.b);
printf("stu.c address %x\n",&stu.c);
printf("stu+1 address %x\n",&stu+1);
stu size 16stu+1的地址正好比stu增加了sizefo(stu)。也就是说在结构体起始地址增加加1,不是简单增加一个字节,或者说向后顺推一个字节,而是增加了整个结构体的大小,移动sizeof(stu)大小,(寻找下一个结构体)。
stu.a address 28fed0
stu.b address 28fed4
stu.c address 28fed8
stu+1 address 28fee0
c语言中,对指针加1,是将该指针向后移动 该指针存储数据类型的大小,也就是说指针增加一个的本意是寻找下一个存储相同数据类型的存储单元。
下面用几个数据类型验证一下:
int temp1;地址如下:
int temp2;
printf("temp1 address %x\n",&temp1);
printf("temp2 address %x\n",&temp2);
temp1 address 28fecctemp1的地址高,现在我们队temp2的地址加1
temp2 address 28fec8
printf("temp1 address %x\n",&temp1);结果如下:
printf("temp2 address %x\n",&temp2);
printf("temp2+1 address %x\n",&temp2+1);
temp1 address 28fecctemp2地址加1操作增加了4个字节,也就是int的大小
temp2 address 28fec8
temp2+1 address 28fecc
再看一下其他数据类型,还有数组
double temp4;结果如下
char temp5[5];
int temp6[5];
printf("temp3 address %x\n",&temp3);
printf("temp3+1 address %x\n",&temp3+1);
printf("temp4 address %x\n",&temp4);
printf("temp4+1 address %x\n",&temp4+1);
printf("temp5 address %x\n",&temp5);
printf("temp5+1 address %x\n",&temp5+1);
printf("temp6 address %x\n",&temp6);
printf("temp6+1 address %x\n",&temp6+1);
temp3 address 28fedftemp3+1增加了1个字节,char类型
temp3+1 address 28fee0
temp4 address 28fed0
temp4+1 address 28fed8
temp5 address 28fecb
temp5+1 address 28fed0
temp6 address 28feb4
temp6+1 address 28fec8
temp4+1增加了8个字节,double字节
temp5+1增加了5*1个字节,长度为5的char数组
temp6+1增加了5*4个字节,长度为5的int数组
话说回来,(&temp6+1)-(&temp)=?多少呢?,肯定是1了
如果用printf("stu.c-stu.b address %d\n",&stu.c-&stu.b)进行操作,编译器很直接
假如我们想要通过结构体的首地址得到成员变量的地址,那就强制让编译器增加数据类型的长度
printf("stu.b address %x\n",(char *)&stu.a+sizeof(stu.a));结果如下:
printf("stu.c address %x\n",(char *)&stu.a+sizeof(stu.a)+sizeof(stu.b));
stu.a address 28fed0最后再回到结构体上,本来还想再试试如何通过结构体首地址访问结构体变量或者通过结构体成员变量获得结构体首地址,结果发现linux内核中有两个宏offsetof和container_of。
stu.b address 28fed4
stu.c address 28fed8
stu.b address 28fed4
stu.c address 28fed8
offsetof宏:获得一个结构体变量成员在此结构体中的偏移量。
container_of宏:从结构体(type)某成员变量(member)指针(ptr)来求出该结构体(type)的首指针。