31.offsetof宏与container_of宏
来源:互联网 发布:电子产品设计软件 编辑:程序博客网 时间:2024/05/23 22:02
31.1.offsetof宏
(1)作用:用宏来计算结构体中某个元素和结构体首地址的偏移量(其本质是通过编译器来帮我们计算)。
(2)原理:我们虚拟1个type类型结构体变量,然后用type.member的方式来访问某个member元素,继而得到member相对于整个变量首地址的偏移量。
(3)学习思路:第1步先学会用offsetof宏;第2步再去理解这个宏的实现原理(见图1)。
31.2.container_of宏
(1)作用:知道某个结构体中某个元素的指针,反推整个结构体变量的指针,继而得到结构体中其它元素的指针。
(2)typeof关键字:typeof(a)即由变量a得到a的类型,typeof就是由变量名得到变量的数据类型。
(3)原理:先用typeof得到member元素的类型,然后通过该类型定义指向member元素的指针,然后用该指针减去该元素相对于整个结构体变量的偏移量(偏移量用offsetof宏得到)后得到整个结构体变量的首地址,再把该地址强制类型转换为type *即可。
(3)学习思路:第1步先学会用container_of宏;第2步再去理解这个宏的实现原理(见图2)。
31.3.学习指南和要求
(1)基本要求:必须要掌握这两个宏的使用,即知道这两个宏接收什么参数,返回什么值,会用这两个宏来写代码,看见代码中别人用这两个宏能理解什么意思。
(2)升级要求:能理解这两个宏的工作原理,能表述出来,有些面试笔试题会这么要求。
(3)高级要求:能自己写出这两个宏,不要着急,慢慢来。
31.struct_macro/* * 公司:XXXX * 作者:Rston * 博客:http://blog.csdn.net/rston * GitHub:https://github.com/rston * 项目:offsetof宏与container_of宏 * 功能:演示offsetof宏与container_of宏的使用。 */#include <stdio.h>// offsetof宏:返回MEMBER元素相对于整个TYPE类型结构体首地址的偏移量// 参数:TYPE为某个结构体类型,MEMBER为TYPE类型结构体中的某个元素#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)// container_of宏:返回整个结构体变量的指针// 参数:ptr为指向结构体中member元素的指针,type为某个结构体类型,member为该结构体中的某个元素#define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); })struct mystruct{ char a; // 偏移量0 int b; // 偏移量4 short c; // 偏移量8 };int main(int argc, char **argv){ // 手动计算偏移量,然后通过指针方式访问结构体元素 struct mystruct s1 = { .a = 'c', .b = 20, .c = 8, }; char *p1 = (char *)&s1; int *p2 = (int *)((char *)&s1 + 4); short int *p3 = (short int *)((char *)&s1 + 8); // *p1 = c. *p2 = 20. *p3 = 8. printf("*p1 = %c. *p2 = %d. *p3 = %d.\n", *p1, *p2, *p3); // 使用offsetof宏 // offsetof(struct mystruct, a) = 0. // (char *)&(s1.a) - (char *)&s1 = 0. printf("offsetof(struct mystruct, a) = %d.\n", offsetof(struct mystruct, a)); printf("(char *)&(s1.a) - (char *)&s1 = %d.\n", (char *)&(s1.a) - (char *)&s1); // offsetof(struct mystruct, b) = 4. // (char *)&(s1.b) - (char *)&s1 = 4. printf("offsetof(struct mystruct, b) = %d.\n", offsetof(struct mystruct, b)); printf("(char *)&(s1.b) - (char *)&s1 = %d.\n", (char *)&(s1.b) - (char *)&s1); // offsetof(struct mystruct, c) = 8. // (char *)&(s1.c) - (char *)&s1 = 8. printf("offsetof(struct mystruct, c) = %d.\n", offsetof(struct mystruct, c)); printf("(char *)&(s1.c) - (char *)&s1 = %d.\n", (char *)&(s1.c) - (char *)&s1); // 使用container_of宏 struct mystruct s2 = { .a = 'd', .b = 30, .c = 5, }; // pS = 0xbfcc8350. &s2 = 0xbfcc8350. struct mystruct *pS = container_of(&(s2.a), struct mystruct, a); printf("pS = %p. &s2 = %p.\n", pS, &s2); return 0;}
0 0
- offsetof与container_of宏
- offsetof与container_of宏
- 31.offsetof宏与container_of宏
- offsetof宏与container_of宏
- offsetof与container_of宏[总结]
- [转载]offsetof与container_of宏
- offsetof与container_of宏[总结]
- offsetof与container_of宏[总结]
- offsetof与container_of宏[总结]
- offsetof与container_of宏[总结]
- offsetof与container_of宏[总结]
- offsetof与container_of宏[总结]
- Offsetof与container_of宏总结
- offsetof与container_of宏[总结]
- offsetof与container_of宏(个人理解)
- (转)offsetof与container_of宏[总结]
- container_of 宏、offsetof 宏 分析
- offsetof宏和container_of宏
- CodeForces 19B Checkout Assistant
- Linux磁盘管理(一)
- 方法的重载例子
- 杭电acm阶段之理工大版
- 正则表达式
- 31.offsetof宏与container_of宏
- 复制控制台内容到TXT文件
- IE浏览器无法加载外部CSS文件
- 热点营销-1
- Struts2 validation 错误信息重复不消失的问题
- Mtalab统计信息处理的一些原理
- java 数字证书生成及证书的加密解密
- 个十百的应用实例
- 深入理解java中的synchronized关键字