【问题标题】:Could someone explain to me the type returns in container_of?有人可以向我解释 container_of 中返回的类型吗?
【发布时间】:2017-10-27 02:49:27
【问题描述】:

谁能给我解释一下这两个宏?

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

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

除了为什么 offset_of 为 (size_t) 而 container_of 为 (char *) 之外,我什么都理解?

(char *) -(size_t) 如何在这个宏中工作?

我原以为它们都是同一类型。比如 char *。

【问题讨论】:

  • 我不知道这怎么不会崩溃。但(char *) - size_t' is just a pointer decrement. When p` 是一个指针,p-4p 递减4*sizeof(*p) 字节。

标签: c linux linux-kernel linux-device-driver


【解决方案1】:

但是 offsetof 返回的值不是指针。顾名思义,它是给定对象中字段的偏移量。它以字节为单位。 size_t 看起来是一个很好的保存值的类型。

c 中的指针运算很简单:p + n 将 p 移动 sizeof(*p)。例如。如果 p 指向大小为 8 的对象,则 p + 1 将其移动 8 以使其指向下一个对象。

char 根据定义 1,因此所有对 char * 指针的指针运算都会移动 1。因此这里使用它来精确移动从 offsetof 获得的量。

【讨论】:

  • 为什么不会崩溃?是因为它在一个宏中,并且 null derefence 被优化掉了吗?
  • 你的意思是 (type *)0)->member 位?这里没有尊重。 typeof 是一个用于获取类型的神奇编译器宏,而 (type *)0 位只是获取成员的废话语法。
  • 是的。我指的是((TYPE *)0)->MEMBER。如果我打电话给offsetof(struct sockaddr, sa_family),这不会将NULL 转换为struct sockaddr *,然后在获取sa_family 的地址之前取消引用它吗?这就是我感到困惑的原因。
  • 那个是&((TYPE *)0)->MEMBER。注意&符号 - 它不尊重任何东西,但会获取地址。地址是通过获取指针的值(此处为 0)并添加到它来计算的。
  • 我想我不同意。由于优先级,& 应用 -> 之后。这就是它如何从 0 中获取偏移量。否则它将是 &((TYPE *) 0),它将尝试获取文字的地址。
猜你喜欢
  • 2013-09-12
  • 1970-01-01
  • 2011-05-08
  • 2019-03-09
  • 2012-04-09
  • 2021-02-18
  • 1970-01-01
  • 2012-04-12
  • 2023-02-08
相关资源
最近更新 更多