当前位置: 首页 > article >正文

关于list_entry

#define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))


       这句话的意思是获取一个结构体中一个成员在这个结构体中的偏移。type *0是为了计算地址方便。意思是在0这个地址看做有一个虚拟的type类型的变量,那么取一个成员再取这个成员的地址,就是这个结构体中这个成员的绝对地址,由于结构体在地址为0的地方,所以这个成员在这个结构体中的相对位置也是这个值了。前面的ptr-...就要和你看到的代码具体联系了。我猜测ptr可能是这个member的指针,而现在想找这个member所在结构体的地址,所以这个member的地址应该减去这个member在这个结构体中的偏移。然后返回这个结构体类型。希望你明白了以上的种种,在你明白的同时希望你能感受到gnu那帮人写c的高超之处,哈哈!~补充:意思就是:

据个例子吧,

typedef struct{
int i;
int j;
}
exp;

 

这个exp结构体占用8个字节,假设声明一个变量。exp e1;那么假如已知e1.j的地址,想知道e1的地址该如何办呢?只要知道j在e1中的偏移,然后把j的地址减去这个偏移就是e1的地址了。在这里,i占据的前4个字节,所以j占据了5-8的字节。

现在我们用你给出的list_entry来解释一下。int *p = e1.j;假设e1的地址是0x100,那么p就是0x104。可是如何才能比较方便的知道p减去4就是e1的地址呢?尤其是我们可能有时候不知道exp这个结构体里面具体什么样子的。

下面的list_entry(p, exp, j);变成:(exp *)((char *)p-(unsigned long)(&((exp *)0)->j)) (exp *)0在0地址上面建立8个字节的exp结构体,->j取出这个0地址上exp结构体里的j成员,&((exp *)0)->j)把这个成员地址取出来,由于j在这个结构体里是在5-8字节,所以从0地址数5个字节就是j所在的位置。

这种方法省去了我们需要预先知道结构体具体什么样子,结构体里成员的位置怎么安排的。p的地址再减去我们刚算出来j所在的位置,就得到e1的地址。

也就是:&e1 == list_entry(p, exp, j)

如果你还是有些困惑你需要找一些C的详细介绍的书籍,查看结构体一章中结构体在内存中的安排情况。

 

不得不佩服linux内核的开发人员,list_entry这个宏实现的真的非常巧妙。其功能是已知一个结构体中的一个成员的地址与此结构体的类型来求得结构体变量的地址。举个例子:

struct kauffman_list {
int a;
int b;
int c;
}list = {5, 6, 7}; 
int main() {
struct kauffman_list *x; 
int *v = &list.b;
printf("a:%d, b:%d, c:%d\n", list.a, list.b, list.c);
//struct kauffman_list *f = ((struct kauffman_list *)0);
x = (struct kauffman_list *)((char *)v -(char *)(&((struct kauffman_list *)0)->b));
printf("a:%d, b:%d, c:%d\n", x->a, x->b, x->c);
return 0;
}


其中x值的取得就类似于list_entry这个宏。其中的奥妙就在于使用0这个特殊的地址来求取b字段和结构体入口地址的距离。

http://www.lryc.cn/news/2420457.html

相关文章:

  • 抖音短视频实操:抖音热门视频的分类特点,如何选择视频内容(上)
  • dlib人脸68个特征点检测 Win10_VS2019编译过程和实验结果
  • windows WinHttp
  • Java之SVN快速入门,服务器VisualSVN和客户端TortoiseSVN的使用,IDEA下的SVN的配置和使用,SVN的目录规范
  • Megaupload关闭波及Filesonic 分享功能被停
  • Android常用系统广播
  • 米粉节”背后的故事——小米网抢购系统开发实践
  • MSN去窗口广告方法http://apatch.org/downloads/
  • 毕业设计:基于python淘宝数据采集分析可视化系统 商品销量数据分析 大数据项目(附源码+文档)✅
  • 数据仓库概念、主要特征以及主流开发语言SQL
  • List 和Set 区别
  • 10条网站易用性技巧
  • vue中props详解
  • BLE基础知识详解
  • C++ 与 CUDA: 搭建高性能计算系统
  • 使用历山手游SDK,轻松搭建高效的游戏联运平台
  • 磊科NW330 LINUX下驱动安装记
  • Apache Spark 基础知识总结及应用示例
  • pthread_cancel手册翻译
  • 微信小程序开发中的数据分析与统计
  • 出身比你好的人,比你聪明,还比你努力
  • Oracle数据库链Database links(dblinks)使用方法
  • Qt 防止程序多次运行
  • 器件选型篇:二极管之肖特基选型
  • 龙生九子 联想06年超越新机官方多图赏上篇
  • 无线震动传感器
  • 亚马逊云aws12个月免费服务器搭建小结
  • 多普达S900 使用详细说明(使用技巧大全)
  • 家中常用药
  • ADUM1201和川土微电子的CA-IS3722HS数字隔离器参数对比