简体   繁体   English

C:这个宏是什么意思?

[英]C: What does this macro mean?

How do you read the second line of this macro? 你怎么看这个宏的第二行? What does (type *)0 mean in this context? 在这种情况下(类型*)0是什么意思?

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

You're finding the type of ((type *)0)->member . 你发现的类型 ((type *)0)->member It's not actually dereferencing the pointer (that would be madness, I tell you. Madness! ) 它实际上并没有取消引用指针(这会是疯狂的,我告诉你。 疯狂!

It's a weirdness of C. Maybe it would make more sense if they wrote typeof(type.member) but sadly that is not allowed. 这是C的一种奇怪。如果他们写下typeof(type.member)会更有意义,但遗憾的是这是不允许的。

A slightly more readable version: 一个稍微可读的版本:

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

In short, the macro defines a usable "test" that can be inserted into if and other statements. 简而言之,宏定义了一个可用的“测试”,可以插入if和其他语句。 The ((type *) 0) casts a NULL reference into the type in question, and then takes the 'member' sub-component of the type. ((type *)0)将NULL引用转换为相关类型,然后获取该类型的“member”子组件。 The typeof() macro will return the type associated with the member sub-"object". typeof()宏将返回与成员子“对象”关联的类型。 So it's creating a constant __mptr variable of the same type as the type.member subcomponent. 所以它创建了一个与type.member子组件相同类型的常量__mptr变量。 For example, if we had: 例如,如果我们有:

typedef struct foo_s {
   int bogus;
   int bar;
} foo;

Then if invoked like this: 然后,如果这样调用:

foo blah;  /* and initialize it of course */
int *myptr = &foo.bar;

foo *result = container_of(myptr, foo, bar);

Then the first line of the macro will turn into the following: 然后宏的第一行将变为以下内容:

const int *__mptr = (myptr);

The second line of the macro then calculates the memory position of the original structure and returns the memory pointer of the structure and properly casts it to that structure, and expanded would look like: 然后,宏的第二行计算原始结构的内存位置,并返回结构的内存指针,并将其正确地转换为该结构,并展开为:

(foo *)( (char *)__mptr - offsetof(foo, bar));

The result is that this: 结果就是:

foo *result = container_of(myptr, foo, bar);

allows you to take the the myptr element within the structure and extract from it the pointer to the original container. 允许您在结构中获取myptr元素,并从中提取指向原始容器的指针。

Now, this isn't useful in the example above because you already have access to the containing structure. 现在,这在上面的示例中没有用,因为您已经可以访问包含的结构。 But pretend you didn't, because the API you're inside of wasn't passed it. 但假装你没有,因为你所在的API没有通过它。 This macro is a tricky way to get the parent container when you normally wouldn't have had it available. 当你通常没有它时,这个宏是获取父容器的一种棘手的方法。

The better thing to do, of course, is to build a better API where this hack isn't necessary. 当然,更好的做法是构建一个更好的API,而不需要这种黑客攻击。 But it's useful if you c 但如果你这样做很有用

(type *)0 is essentially NULL . (type *)0基本上是NULL The second line takes the address of the value you gave it and substracts its positions in the struct. 第二行获取您给出的值的地址,并在结构中减去其位置。 that gives you the address of the struct 它为您提供了结构的地址

It's just like how offsetof(type, member) is defined. 这就像offsetof(type,member)的定义一样。

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

(TYPE *)0 casts 0 to a pointer pointing to 0 of type TYPE, and ((TYPE *)0)->member points to the member of TYPE. (TYPE *)0将0转换为指向TYPE类型的0的指针,((TYPE *)0) - >成员指向TYPE的成员。

Actually, the second line is redundant and only for typechecking. 实际上,第二行是多余的,仅用于类型检查。

#define container_of(ptr, type, member) ({\ 
 (type *)( (char *)ptr - offsetof(type,member) );}) 

would have same semantics, except for type checking capability. 除了类型检查功能外,它们具有相同的语义。

Look at: Rationale behind the container_of macro in linux/list.h 请看: linux / list.h中container_of宏背后的原理

See also for general explanation: http://www.kroah.com/log/linux/container_of.html 另请参阅一般说明: http//www.kroah.com/log/linux/container_of.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM