fbpx
维基百科

offsetof

C语言offsetof()宏,是定义在stddef.h。用于求出一个structunion数据类型的给定成员的size_t类型的字节偏移值。offsetof()宏有两个参数,分别是结构名与结构内的成员名。不能声明为C原型。[1]

实现 编辑

传统实现依赖于编译器对指针不是很挑剔。它假定结构的地址为0,然后获得成员的偏移值:

#define offsetof(st, m) ((size_t)&(((st *)0)->m)) 

上述定义在C11语言标准下是未定义行为[2] 因为它对空指针做了解引用(dereference)。GCC现在定义该宏为:[3]

#define offsetof(st, m) __builtin_offsetof(st, m) 

这种内置对C++的classstruct也适用。[4]

用途 编辑

Linux内核使用offsetof()来实现container_of(),这允许类似于mixin类型以发现包含它的结构:[5]

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

container_of()宏被用于从指向内嵌成员的指针获得外包的结构的指针。如链表my_struct:

struct my_struct {  const char *name;  struct list_node list; }; extern struct list_node * list_next(struct list_node *); struct list_node *current = /* ... */ while(current != NULL){  struct my_struct *element = container_of(current, struct my_struct, list);  printf("%s\n", element->name);  current = list_next(&element->list); } 

Linux内核实现container_of()时,使用了GNU C扩展statement expressions.[6]下述实现也能确保类型安全:

#define container_of(ptr, type, member) ((type *)((char *)(1 ? (ptr) : &((type *)0)->member) - offsetof(type, member))) 

粗看起来,上述的不寻常的?:条件运算符是不适当的。可以写成更简单的形式:

#define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member))) 

这种写法忽略了检查ptr的类型是否是member的类型,而Linux内核的实现需要这种安全检查。而?:条件运算符要求如果操作数是一个类型的两个指针值,那么它们应当是兼容的类型。所以第三个操作数虽然不会被使用,但编译器要检查(ptr)&((type *)0)->member是不是兼容的指针类型。

局限性 编辑

C++03要求offsetof限于POD类型。C++11要求offsetof限于标准布局类型[7] 但仍存在未定义行为。特别是虚继承情形。[8] 下述代码用gcc 4.7.3 amd64编译器,产生的结果是有问题的:

#include <stddef.h> #include <stdio.h> struct A {  int a;  virtual void dummy() {} }; struct B: public virtual A {  int b; }; int main() {  printf("offsetof(A,a) : %zu\n", offsetof(A, a));  printf("offsetof(B,b) : %zu\n", offsetof(B, b));  return 0; } 

Output is:

offsetof(A,a) : 8 offsetof(B,b) : 8 

参考文献 编辑

  1. ^ offsetof reference. MSDN. [2010-09-19]. (原始内容于2011-10-10). 
  2. ^ Does &((struct name *)NULL -> b) cause undefined behaviour in C11?. [2015-02-07]. (原始内容于2015-02-07). 
  3. ^ GCC offsetof reference. Free Software Foundation. [2010-09-19]. (原始内容于2010-07-24). 
  4. ^ what is the purpose and return type of the __builtin_offsetof operator?. [2012-10-20]. (原始内容于2014-12-15). 
  5. ^ Greg Kroah-Hartman. container_of(). Linux Journal. June 2003 [2010-09-19]. (原始内容于2010-02-13). 
  6. ^ Statements and Declarations in Expressions. Free Software Foundation. [2016-01-01]. (原始内容于2016-01-05). 
  7. ^ offsetof reference. cplusplus.com. [2016-04-01]. (原始内容于2016-03-30). 
  8. ^ Steve Jessop. Why can't you use offsetof on non-POD structures in C. Stack Overflow. July 2009 [2016-04-01]. (原始内容于2019-10-19). 

offsetof, c语言的, 是定义在stddef, 用于求出一个struct或union数据类型的给定成员的size, t类型的字节偏移值, 宏有两个参数, 分别是结构名与结构内的成员名, 不能声明为c原型, 目录, 实现, 用途, 局限性, 参考文献实现, 编辑传统实现依赖于编译器对指针不是很挑剔, 它假定结构的地址为0, 然后获得成员的偏移值, define, size, 上述定义在c11语言标准下是未定义行为, 因为它对空指针做了解引用, dereference, gcc现在定义该宏为, define, . C语言的offsetof 宏 是定义在stddef h 用于求出一个struct或union数据类型的给定成员的size t类型的字节偏移值 offsetof 宏有两个参数 分别是结构名与结构内的成员名 不能声明为C原型 1 目录 1 实现 2 用途 3 局限性 4 参考文献实现 编辑传统实现依赖于编译器对指针不是很挑剔 它假定结构的地址为0 然后获得成员的偏移值 define offsetof st m size t amp st 0 gt m 上述定义在C11语言标准下是未定义行为 2 因为它对空指针做了解引用 dereference GCC现在定义该宏为 3 define offsetof st m builtin offsetof st m 这种内置对C 的class或struct也适用 4 用途 编辑Linux内核使用offsetof 来实现container of 这允许类似于mixin类型以发现包含它的结构 5 define container of ptr type member const typeof type 0 gt member mptr ptr type char mptr offsetof type member container of 宏被用于从指向内嵌成员的指针获得外包的结构的指针 如链表my struct struct my struct const char name struct list node list extern struct list node list next struct list node struct list node current while current NULL struct my struct element container of current struct my struct list printf s n element gt name current list next amp element gt list Linux内核实现container of 时 使用了GNU C扩展statement expressions 6 下述实现也能确保类型安全 define container of ptr type member type char 1 ptr amp type 0 gt member offsetof type member 粗看起来 上述的不寻常的 条件运算符是不适当的 可以写成更简单的形式 define container of ptr type member type char ptr offsetof type member 这种写法忽略了检查ptr的类型是否是member的类型 而Linux内核的实现需要这种安全检查 而 条件运算符要求如果操作数是一个类型的两个指针值 那么它们应当是兼容的类型 所以第三个操作数虽然不会被使用 但编译器要检查 ptr 与 amp type 0 gt member是不是兼容的指针类型 局限性 编辑C 03要求offsetof限于POD类型 C 11要求offsetof限于标准布局类型 7 但仍存在未定义行为 特别是虚继承情形 8 下述代码用gcc 4 7 3 amd64编译器 产生的结果是有问题的 include lt stddef h gt include lt stdio h gt struct A int a virtual void dummy struct B public virtual A int b int main printf offsetof A a zu n offsetof A a printf offsetof B b zu n offsetof B b return 0 Output is offsetof A a 8 offsetof B b 8参考文献 编辑 offsetof reference MSDN 2010 09 19 原始内容存档于2011 10 10 Does amp struct name NULL gt b cause undefined behaviour in C11 2015 02 07 原始内容存档于2015 02 07 GCC offsetof reference Free Software Foundation 2010 09 19 原始内容存档于2010 07 24 what is the purpose and return type of the builtin offsetof operator 2012 10 20 原始内容存档于2014 12 15 Greg Kroah Hartman container of Linux Journal June 2003 2010 09 19 原始内容存档于2010 02 13 Statements and Declarations in Expressions Free Software Foundation 2016 01 01 原始内容存档于2016 01 05 offsetof reference cplusplus com 2016 04 01 原始内容存档于2016 03 30 Steve Jessop Why can t you use offsetof on non POD structures in C Stack Overflow July 2009 2016 04 01 原始内容存档于2019 10 19 取自 https zh wikipedia org w index php title Offsetof amp oldid 63422639, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。