它是为计算获取字节级地址.否则,指针算术将根据所指向的类型,由于offsetof
计算以字节为单位的偏移量而中断.
char *
在这样的低级基元内部,转换是很常见的,因为有时你真的需要将内存视为"字节数组"并在该级别操作它.
以此结构为例:
struct demo { int foo; float bar; };
现在,如果我们这样做:
struct demo test; float *intptr = &test.bar;
我们应该能够得到一个test
使用指针container_of()
:
struct demo *owner = container_of(intptr, struct demo, bar);
这将扩展到:
struct demo *owner = {( const typeof( ((struct demo*)0)->bar) *__mptr = (intptr); (struct demo*)( (char *)__mptr - offsetof(struct demo,bar) );})
所以第一行声明了一个float
指针__mptr
并将参数值复制到它.
第二行将成员指针强制转换char *
,然后减去bar
内部的偏移量struct demo
(如果sizeof (int)
为4则为4),从而"备份"到整个结构的地址test
.
如果演员char *
不在那里,那么4
就会被解释为float
(因为__mptr
是float *
),这显然会过多地支持(16个字节而不是4个,假设float
也是4个字节)导致可怕的破损.
请注意,包含{(
扩展的语法container_of()
是GCC扩展; 这在标准C中不起作用.
请参阅本页面更上很多container_of()
.
它是为计算获取字节级地址.否则,指针算术将根据所指向的类型,由于offsetof
计算以字节为单位的偏移量而中断.
char *
在这样的低级基元内部,转换是很常见的,因为有时你真的需要将内存视为"字节数组"并在该级别操作它.
以此结构为例:
struct demo { int foo; float bar; };
现在,如果我们这样做:
struct demo test; float *intptr = &test.bar;
我们应该能够得到一个test
使用指针container_of()
:
struct demo *owner = container_of(intptr, struct demo, bar);
这将扩展到:
struct demo *owner = {( const typeof( ((struct demo*)0)->bar) *__mptr = (intptr); (struct demo*)( (char *)__mptr - offsetof(struct demo,bar) );})
所以第一行声明了一个float
指针__mptr
并将参数值复制到它.
第二行将成员指针强制转换char *
,然后减去bar
内部的偏移量struct demo
(如果sizeof (int)
为4则为4),从而"备份"到整个结构的地址test
.
如果演员char *
不在那里,那么4
就会被解释为float
(因为__mptr
是float *
),这显然会过多地支持(16个字节而不是4个,假设float
也是4个字节)导致可怕的破损.
请注意,包含{(
扩展的语法container_of()
是GCC扩展; 这在标准C中不起作用.
请参阅本页面更上很多container_of()
.