c语言新手求教一个linux内核代码的问题

yxzzkx 2015-04-16 09:54:55
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)

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

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

size_t 是unsigned long
typedef struct xxx
{
type1 member;
……(结构体中其他域)
}type;
定义变量:
type a;
type * b;
type1 * ptr;

&((type *)0)->member取得的是个什么,为什么要转为u long
为什么要用__mptr当中间变量,不直接用ptr。
最后用char型的__mptr减ulong的偏移量可以得到该结构体的地址吗?
...全文
250 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
yxzzkx 2015-04-17
  • 打赏
  • 举报
回复
为什么要用char型的指针减ul型的呢?为什么要把member的地址转成ul型。。。
Jacob_wxy 2015-04-17
  • 打赏
  • 举报
回复
首先第一个问题是 通过 typeof( ((type *)0)->member ) 获取member成员的类型, 第二个问题是 如果直接用ptr 做偏移, ptr本身指向就变了 第三个问题是 获取到的是这个结构起始地址 我也是新手 欢迎指教!
nswcfd 2015-04-17
  • 打赏
  • 举报
回复
笔误,不是编译是偏移。
nswcfd 2015-04-17
  • 打赏
  • 举报
回复
2. 为什么需要中间变量_mtpr,因为传入的参数ptr,不见得就是个简单的指针变量,也有可能是个表达式(因为这是宏)。 比如contailer_of(ptr + 1, struct XXX, member), 如果去掉_mptr,那么就变成了(char *)ptr + 1 - offset,结果就是错误的(应该是((char *)(ptr + 1)) - offset,注意括号) 3. 为什么要转换成char *,因为在c语言里面,(((type *)ptr) - offset) == ((char *)ptr) - sizeof(type) * offset。 不是往前挪offset个字节,而是往前挪offset个结构。 显然这些需要的是字节语义。 因为 成员的地址 = 结构的地址 + 字节偏移, 所以 结构的地址 = 成员的地址 - 字节编译。(以字节为单位计算)
nswcfd 2015-04-17
  • 打赏
  • 举报
回复
可以自己试试,去掉size_t之后能否编译通过。 不转的话,就变成(char *)ptr - (XXX *)offset,其中XXX是member的类型, c语言是不允许不同类型的指针做减法的。

4,436

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧