基于VC++ 6.0下的offsetof(TYPE, MEMBER)个人实验心得
最近在学习linux下的内核链表,发现linux的内核链表不同于传统的链表,于是打算把这套内核链表移植出来,方便以后使用,不过在移植offsetof(TYPE, MEMBER)这个宏的时候遇到了很多之前不懂的问题,经过几天的努力终于把offsetof这个宏弄的明明白白了。
正确源代码:
1 #include "stdafx.h" 2 3 4 #define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER ) 5 6 typedef struct _test 7 { 8 char i; 9 double k; 10 int j; 11 }Test; 12 13 14 int main(int argc, char* argv[]) 15 { 16 Test a; 17 a.i = 1; 18 a.j = 2; 19 a.k = 3; 20 int *p = &(a.j); 21 printf("j元素的偏移量:%p\n", offsetof(Test, j)); //打印j元素在相对于Test结构的地址偏移量 22 printf("j元素的地址:%p\n", p); //打印j元素的地址 23 printf("j地址减去偏移量之后的地址:%p\n", (char *)p - offsetof(Test, j)); //打印j地址减去偏移量之后的地址值 24 printf("Test结构a的地址:%p\n", &a); //打印Test结构a的地址值,若j地址减去偏移量 = a地址值,则offsetof正确 25 printf("Test结构的大小:%d\n", sizeof(struct _test)); //打印Test结构的大小 26 return 0; 27 }
遇到的问题:
1. 在offsetof宏中为什么要用(size_t)强制转换?
由上图可得答案。
2. 为什么在 printf("j地址减去偏移量之后的地址:%p\n", (char *)p - offsetof(Test, j)); 这句要在p前面加上强制转换(char *)?
假设两种情况:
1、不加强制转换
实验结果:
有实验结果可以看到:实验结果的3,4行的地址不相等,则说明实验结果错误;
2、加强制转换
实验结果:
可以看到,实验结果正确。
那么为什么要加强制转换,实验结果才正确呢?
原因:因为p是一个指针,指针减去一个数,等于指针的值减去指针类型的倍数,例如,int *p=&a;
p = p - 1;
那么相当于p的值减去了4(因为int 型指针大小为4个字节)
以上为我个人见解,不一定正确,但可以参考。