container_of()宏中的赋值运算符如何工作

时间:2013-07-06 19:29:06

标签: c linux linux-device-driver

我曾尝试在linux内核中使用container_of宏。

我通过谷歌获得的内容如下

#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) );})

#define CONT(prt, type, mem) container_of((prt), type, mem)

struct test {
 int a;
};

struct m {
 int b;
 struct test t;
 int c;
};

int main(int argc, char *argv[])
{
 /* existing structure */
 struct m *ma;
 ma = malloc(sizeof(struct m));
 ma->t.a = 5;
 ma->b = 3;
 /* pointer to existing entry */    
 struct test *te = &ma->t;

 struct m *m = CONT(te, struct m, t);

 printf("m->b = %d\n", m->b);

 return EXIT_SUCCESS;
}

O / P m-> b = 3

但我对* m的分配有疑问。我试过跟随

#include <stdio.h>

int main()
{
        int x = (int k = 9;k-2;);
        printf("x= %d k = %d",x,k);
}

O / P

one.c:5: error: expected ‘)’ before ‘k’
one.c:5: error: expected expression before ‘;’ token
one.c:6: error: ‘k’ undeclared (first use in this function)
one.c:6: error: (Each undeclared identifier is reported only once
one.c:6: error: for each function it appears in.)

如果这个赋值在这里是错误的那么它是如何在宏的容器中工作的。上面两个的区别是什么。(我知道一个是宏,其他是正常的声明,但宏扩展后看起来都一样)

注意:对不起,因为这可能很简单,但我无法弄明白。

kinldy为我的dobut提供了一些解决方案。

2 个答案:

答案 0 :(得分:3)

这是使用特殊的gcc功能,即块表达式({ })。这些允许在表达式中具有对象定义。此构造中的最后一个语句确定块表达式的值。

所以你错过了测试用例表达式中的额外{ }

此外:

  • 该宏中没有赋值,只是初始化局部变量
  • typeof运算符中还有一个gcc扩展名

答案 1 :(得分:1)

我正在添加我对这个问题的回答,因为我得到了一些意见。可能会帮助其他人。

#include <stdio.h>
int main()
{
int x = ({int k = 9;k-2;});
printf("x = %d",x);

 }

O / P x = 7

正如Jens所说的那样,我已经错过了{ },但除此之外,我打印的k值不正确,因为({ })中创建的所有值都是临时的并且一旦评估了表达式的值就会删除。

http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs