- 浏览: 202769 次
- 性别:
- 来自: 重庆
文章分类
最新评论
结构体内变量相对便宜与list_entry()宏
- 博客分类:
- c++
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
ptr是指向list_head类型链表的指针,type为一个结构,而member为结构type中的一个域,类型为list_head,这个宏返回指向type结构的指针。在内核代码中大量引用了这个宏,因此,搞清楚这个宏的含义和用法非常重要。
设有如下结构体定义:
typedef struct xxx
{
……(结构体中其他域,令其总大小为size1)
type1 member;
……(结构体中其他域)
}type;
定义变量:
type a;
type * b;
type1 * ptr;
执行:
ptr=&(a.member);
b=list_entry(ptr,type,member);
则可使b指向a,得到了a的地址。
如何做到的呢?
先看&((type *)0)->member:
把“0”强制转化为指针类型,则该指针一定指向“0”(数据段基址)。因为指针是“type *”型的,所以可取到以“0”为基地址的一个type型变量member域的地址。那么这个地址也就等于member域到结构体基地址的偏移字节数。
再来看 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))):
(char *)(ptr)使得指针的加减操作步长为一字节,(unsigned long)(&((type *)0)->member)等于ptr指向的member到该member所在结构体基地址的偏移字节数。二者一减便得出该结构体的地址。转换为 (type *)型的指针,大功告成。
--------------------------------------------------------------------------------------------------
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
--------------------------------------------------------------------------------------------------
指针ptr指向结构体type中的成员member;通过指针ptr,返回结构体type的起始地址,如图2。
type
|----------|
| |
| |
|----------|
ptr--> | member --|
|----------|
| |
| |
|----------|
图2 list_entry()宏的示意图
为了便于理解,在此给予进一步说明。
例如my_list结构:
struct my_list{
void *mydata;
struct list_head list;
}; struct list_head *pos;
则list_entry(pos, mylist, list)宏,就可以根据pos的值,获取mylist的地址,也就是指向mylist的指针,这样,我们就可以存取mylist->mydata字段了。
可为什么能够达到这样的效果?
list_entry(pos, mylist, list) 展开以后为:
((struct my_list *)((char *)(pos) - (unsigned long)(&((struct my_list *)0)->list)))
这看起来会使大多数人眩晕,但仔细分析一下,实际很简单。
((size_t) &(type *)0)->member)把0地址转化为type结构的指针,然后获取该结构中member成员的指针,并将其强制转换为size_t类型。于是,由于结构从0地址开始定义,因此,这样求出member的成员地址,实际上就是它在结构中的偏移量。
发表评论
-
C++的原子操作
2012-12-20 17:43 4658在多进程(线程)访问资源时,能够确保所有其他的进程(线程 ... -
匿名namespace的作用以及它与static的区别
2012-12-20 17:24 1773一。匿名namespace的作用 在C语言中,如果我们 ... -
C++类型萃取技术
2012-12-19 15:16 1117Traits技术可以用来获得一个 类型 的相关信息的。 ... -
数值压缩存储方法Varint
2012-12-19 14:35 819转自:http://www.cnblogs.com/smark ... -
TypeList
2012-12-19 13:49 1120转自:http://blog.csdn.n ... -
template <unsigned int N>
2012-12-19 11:51 1466详见:http://stackoverflow.com/ ... -
二维指针*(void **)的研究(uC/OS-II案例)
2012-12-19 22:20 3259原文 : http://blog.csdn ... -
多级指针和链表
2012-12-18 22:28 0如果看到一个声明:t ... -
理解*(void**)b
2012-12-18 22:03 0#include <stdio.h> ... -
STL标准库:Allocator能做什么
2012-12-18 20:10 0The Standard Librarian: Wha ... -
三种的allocator实现源代码的对比
2012-12-18 19:55 1286转自:http://blog.csdn.net ... -
声明与函数、函数指针---(*(void (*)( ) )0)( ) 解析
2012-12-18 17:33 1083概述 在很 ... -
c++模板(类型依赖)说明例子
2012-12-18 16:57 1131#include <iostream> # ... -
C++中三种new的用法
2012-12-18 16:44 1817我评价自己的C++水平还未入门的确不够准确,应该是远远未 ... -
C++,永久改变你写异常安全代码的方式(神奇的Loki::ScopeGuard)
2012-12-17 20:19 2483作者:Andrei Alexandrescu and P ... -
C++的make_pair函数
2012-12-17 17:19 3436Pairs C++标准程序库中凡是“必须返回两 ... -
C++的explicit构造函数
2012-12-13 15:59 628按照默认规定,只有一个参数的构造函数也定义了一个隐式转换 ...
相关推荐
本书不仅说明了插口API和协议族的关系以及主机实现与路由器实现的差别。还介绍了4.4BSD-Lite版的新的特点,如多播、长肥管道支持、窗口缩放、时间戳选项以及其他主题等等。读者阅读本书时,应当具备卷1中阐述的关于...
>>> from drgn.helpers.linux import list_for_each_entry >>> for mod in list_for_each_entry( ' struct module ' , ... prog[ ' modules ' ].address_of_(), ... ' list ' ): ... if mod.refcnt.counter > 10 : ....
(gdb) print find_entry(1,0) l 数据结构和其他复杂对象 (gdb) print *table_start $8={e=reference=’\000’,location=0x0,next=0x0} l 值的历史成分 (gdb)print $1 ($1为历史记录变量,在以后可以直接引用 $1 的值)...
//创建进程信息变量,用于保存信息 info->dwSize=sizeof(PROCESSENTRY32); //设置块大小 int i=0; if(Process32First(handle,info))//开始枚举进程 { if(GetLastError()==ERROR_NO_MORE_FILES ) { ...
LIST_ENTRY list_head; KSPIN_LOCK list_lock; KEVENT request_event; PVOID thread_pointer; BOOLEAN terminate_thread; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; media_in_device是指这个设备是否已经...
可以使用DEFINE命令设置系统变量EDITOR来改变文本编辑器的类型,在login.sql文件中定义如下一行 DEFINE_EDITOR=vi f、运行命令文件 SQL>START test SQL>@test 常用SQL*Plus语句 a、表的创建、修改、删除 创建表的...
+0x010 ThreadListEntry : _LIST_ENTRY [ 0xff70fbd0 - 0xff70fbd0 ] +0x018 IoStatus : _IO_STATUS_BLOCK +0x020 RequestorMode : 1 '' +0x021 PendingReturned : 0 '' +0x022 StackCount : 1 '' +0x023 ...
ls -l (list)列表显示文件(默认按文件名排序), 显示文件的权限、硬链接数(即包含文件数,普通文件是1,目录1+)、用户、组名、大小、修改日期、文件名。 ls -t (time)按修改时间排序,显示目录和文件。 ls -lt 是...
其调用与 CFG_NAND_LEGACY 宏有 关,如果没有定义这个宏,系统调用 drivers/nand/nand.c 中的 nand_init();否则调用自己在 本文件中的 nand_init()函数,本例使用后者。fs2410.c代码如下: #if defined(CONFIG_CMD...
3.2.2 使用LIST_ENTRY 41 3.2.3 使用长长整型数据 43 3.3 自旋锁 44 3.3.1 使用自旋锁 44 3.3.2 在双向链表中使用自旋锁 45 3.3.3 使用队列自旋锁提高性能 46 第4章 文件、注册表、线程 47 4.1 文件操作 47 ...
setmenu --graphic-entry=类型=菜单行数=菜单列数=图形宽(像素)=图形高(像素)=菜单行间距(像素) 菜单项0的路径文件名 类型: 位0:高亮指定颜色 位1:高亮颜色翻转 位2:高亮显示线框 位7:背景透明(最好使用黑色...
// 为提高效率而采用的临时变量 private IPLocation loc; private byte[] buf; private byte[] b4; private byte[] b3; private String province = null; private String city = null; private ...
2.5 变量与常量 可能你已经注意到,变量都有一个美元符号($)的前缀。所有变量都是局部变量,为了使得定义的函数中可以使用外部变量,使用global语句。而你要将该变量的作用范围限制在该函数之内,使用static语句...
3.2.2 使用LIST_ENTRY 41 3.2.3 使用长长整型数据 43 3.3 自旋锁 44 3.3.1 使用自旋锁 44 3.3.2 在双向链表中使用自旋锁 45 3.3.3 使用队列自旋锁提高性能 46 第4章 文件、注册表、线程 47 4.1 文件操作 47 ...
当forEach 的items属性中的表达式的值是java.util.Map时,则var中命名的变量的类型就是 java.util.Map.Entry。这时var=entry的话,用表达式${entry.key}取得键名。 用表达${entry.value}得到每个entry的值。这是...
根据实际情况修改build_ethercat-1.5.2.sh中以下几个变量: output_dir='output' #编译输出目录 module_install_dir='module_install' #内核模块安装目录 kernel_source_dir='/mnt/fs_ext/imx6/linux-3.0.35' ...
用法示例: chain = IndexedChain(treename)chain.Add(filename)chain.retrieve_entrylists([cut1, cut2, cut3])# loop on cut, then loop on entryfor cut in chain.tcuts_with_existing_list(): chain.preselect...
检查与进程、线程和作业相关的数据结构和算法;观察Windows如何管理虚拟内存和物理内存;理解NTFS的操作和格式,诊断文件系统访问问题;从上往下查看Windows的网络栈,包括映射、API、名称解析和协议驱动程序;诊断...
List 标记: interface ArrayList 标记: class CRUD : boolean add(E e) boolean remove(Object o) E set(int index, E element) E get(int index) 底层数组实现,查询快,增删慢 LinkedList 标记: ...
2.8 我听说结构可以赋给变量也可以对函数传入和传出。为什么K&R1却明确说明不能这样做? 25 2.9 为什么不能用内建的==和!=操作符比较结构? 26 2.10 结构传递和返回是如何实现的? 26 2.11 如何向接受结构参数...