Chinaunix首页 | 论坛 | 博客
  • 博客访问: 335158
  • 博文数量: 79
  • 博客积分: 2466
  • 博客等级: 大尉
  • 技术积分: 880
  • 用 户 组: 普通用户
  • 注册时间: 2006-02-07 16:47
文章分类

全部博文(79)

文章存档

2014年(3)

2012年(7)

2011年(14)

2010年(2)

2009年(2)

2008年(2)

2007年(18)

2006年(31)

分类: C/C++

2006-12-12 23:02:44

#include
#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 container(ptr, type, member) (type *)( (char *)ptr - offsetof(type,member) )
struct tag_test {
  int i;
  char s[32];
  void *p;
};

#define print_addr(var) printf(" "#var": %p\n", var)
int
main(void) {
  struct tag_test tstr;
  struct tag_test *ca = container_of(&(tstr.p), struct tag_test, p);
  struct tag_test *ca2 = container(&(tstr.p), struct tag_test, p);
  print_addr(&tstr);
  print_addr(ca);
  print_addr(ca2);
  return 0;
}
/cygdrive/e/wrk/cpp/c/temp $ ./a.exe
 &tstr: 0x22eee0
 ca: 0x22eee0
 ca2: 0x22eee0
/cygdrive/e/wrk/cpp/c/temp $

说明:offsetof是求MEMBER在TYPE结构体中的偏移量,container_of是给定结构体某个成员的地址反推其结构体地址。两个宏实现的方法都很直观,无需多解释。倒是有一点:container_of是linux/kernel.h中定义的,其中用到的typeof操作符和语句表达式(即“({ statements })”这种写法)都是gcc对C的扩展,不是标准C。这两个feature的详细解释作为附录贴在本文末尾。我在程序里照猫画虎写了一个container宏,运行结果证明它和container_of功能一样,而且没有用到任何非标准C的东西。当然了,写Linux内核的人都是不知道比我牛多少倍的牛人,他们那样写一定是有他们的道理,只是我目前的水平还理解不了。先这么放着吧,等什么时候顿悟了再补上这一段。
typeof:
Another way to refer to the type of an expression is with typeof. The syntax of using of this keyword looks like sizeof, but the construct acts semantically like a type name defined with typedef.
There are two ways of writing the argument to typeof: with an expression or with a type. Here is an example with an expression:
     typeof (x[0](1))
This assumes that x is an array of pointers to functions; the type described is that of the values of the functions.
Here is an example with a typename as the argument:
     typeof (int *)
Here the type described is that of pointers to int.
A typeof-construct can be used anywhere a typedef name could be used. For example, you can use it in a declaration, in a cast, or inside of sizeof or typeof.
typeof is often useful in conjunction with the statements-within-expressions feature. Here is how the two together can be used to define a safe “maximum” macro that operates on any arithmetic type and evaluates each of its arguments exactly once:
     #define max(a,b) \
       ({ typeof (a) _a = (a); \
           typeof (b) _b = (b); \
         _a > _b ? _a : _b; })
Some more examples of the use of typeof:
This declares y with the type of what x points to.
          typeof (*x) y;
This declares y as an array of such values.
          typeof (*x) y[4];

Statements and Declarations in Expressions
A compound statement enclosed in parentheses may appear as an expression in GNU C. This allows you to use loops, switches, and local variables within an expression.
Recall that a compound statement is a sequence of statements surrounded by braces; in this construct, parentheses go around the braces. For example:
     ({ int y = foo (); int z;
        if (y > 0) z = y;
        else z = - y;
        z; })
is a valid (though slightly more complex than necessary) expression for the absolute value of foo ().
The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct. (If you use some other kind of statement last within the braces, the construct has type void, and thus effectively no value.)
This feature is especially useful in making macro definitions “safe” (so that they evaluate each operand exactly once). For example, the “maximum” function is commonly defined as a macro in standard C as follows:
     #define max(a,b) ((a) > (b) ? (a) : (b))
But this definition computes either a or b twice, with bad results if the operand has side effects. In GNU C, if you know the type of the operands (here taken as int), you can define the macro safely as follows:
     #define maxint(a,b) \
       ({int _a = (a), _b = (b); _a > _b ? _a : _b; })
 
阅读(3970) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~