转自:http://www.linuxidc.com/Linux/2015-07/120014.htm

本文首先介绍Linux下的经典宏定义,感受极客的智慧,然后根据该经典定义为下篇文章作铺垫。

offsetof宏定义:

// 获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量。
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

说明:获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量。
1.( (TYPE *)0 ) 将零转型为TYPE类型指针,即TYPE类型的指针的地址是0。
2.((TYPE *)0)->MEMBER    访问结构中的数据成员。
3.&( ( (TYPE *)0 )->MEMBER )  取出数据成员的地址。由于TYPE的地址是0,这里获取到的地址就是相对MEMBER在TYPE中的偏移。
4.(size_t)(&(((TYPE*)0)->MEMBER))  结果转换类型。对于32位系统而言,size_t是unsigned int类型;对于64位系统而言,size_t是unsigned long类型。

使用示例:

struct student
{
 char gender;
 int id;
 int age;
 char name[20];
};

int _tmain(int argc, _TCHAR* argv[])
{
 int gender_offset, id_offset, age_offset, name_offset;

gender_offset = offsetof(struct student, gender);
 id_offset = offsetof(struct student, id);
 age_offset = offsetof(struct student, age);
 name_offset = offsetof(struct student, name);

printf("gender_offset = %d\n", gender_offset);
 printf("id_offset = %d\n", id_offset);
 printf("age_offset = %d\n", age_offset);
 printf("name_offset = %d\n", name_offset);

system("pause");
 return 0;
}
//结果:
/*
gender_offset = 0
id_offset = 4 //字节对其
age_offset = 8
name_offset = 12
*/

offsetof图解

TYPE是结构体,它代表"整体";而MEMBER是成员,它是整体中的某一部分。

container_of宏定义:

#define container_of(ptr, type, member) ({          \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

说明:根据"结构体(type)变量"中的"域成员变量(member)的指针(ptr)"来获取指向整个结构体变量的指针。
1. typeof( ( (type *)0)->member )    取出member成员的变量类型。
2.const
typeof( ((type *)0)->member ) *__mptr = (ptr)   
定义变量__mptr指针,并将ptr赋值给__mptr。经过这一步,__mptr为member数据类型的常量指针,其指向ptr所指向的地址。
3. (char *)__mptr    将__mptr转换为字节型指针。
4. offsetof(type,member))    就是获取"member成员"在"结构体type"中的位置偏移。
5. (char *)__mptr - offsetof(type,member))    就是用来获取"结构体type"的指针的起始地址(为char *型指针)。
6.(type *)( (char *)__mptr - offsetof(type,member) )    就是将"char *类型的结构体type的指针"转换为"type *类型的结构体type的指针"。
7.反斜杠“/”表示行连接

更多详情见请继续阅读下一页的精彩内容http://www.linuxidc.com/Linux/2015-07/120014p2.htm

最新文章

  1. ASP.NET 判断客户端是否为手机的函数
  2. C# 中GUID生成格式的四种格式
  3. WPF 3D模型 3D场景
  4. 手动配置WCF宿主的.config文件遇到的几种错误
  5. 通信原理读书笔记:常规AM调制的功率
  6. ACM YTU 2018 母牛的故事
  7. Java HttpClient
  8. include与jsp:include区别
  9. angular 过滤排序
  10. Yii 中出现“<?= ... ?>”是什么意思?
  11. js分享功能
  12. Libgdx教程目录
  13. 文件操作命令(replace)
  14. (dev mode) install CONSUL on ubuntu
  15. cocos2d-x 2.1.4 项目配置过程
  16. 解决VS2010使用mscomm控件无法接收数据的问题
  17. macos下安装oh-my-zsh和zsh-autosuggestion
  18. AptanaStudio3+PHP程序远程调试的方法和步骤
  19. javascript的中的new
  20. P2475 [SCOI2008]斜堆

热门文章

  1. Ubuntu下使用Git_3
  2. 用node是踩过的一些坑
  3. 在阿里云上遇见更好的Oracle(一)
  4. Leetcode 678.有效的括号字符串
  5. tensorflow学习笔记(2)-反向传播
  6. 简易cmake多文件多目录工程模板
  7. Eclipse打不开,闪退
  8. ARC075 E.Meaningful Mean(树状数组)
  9. 2018-2-6考试(COCI2014/2015 Contest#5)
  10. 【BZOJ 1146】[CTSC2008]网络管理Network