fbpx
Wikipedia

offsetof

C's offsetof() macro is an ANSI C library feature found in stddef.h. It evaluates to the offset (in bytes) of a given member within a struct or union type, an expression of type size_t. The offsetof() macro takes two parameters, the first being a structure or union name, and the second being the name of a subobject of the structure/union that is not a bit field. It cannot be described as a C prototype.[1]

Implementation edit

The "traditional" implementation of the macro relied on the compiler obtaining the offset of a member by specifying a hypothetical structure that begins at address zero:

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

This can be understood as taking a null pointer of type structure st, and then obtaining the address of member m within said structure. While this implementation works correctly in many compilers, it has generated some debate regarding whether this is undefined behavior according to the C standard,[2] since it appears to involve a dereference of a null pointer (although, according to the standard, section 6.6 Constant Expressions, Paragraph 9, the value of the object is not accessed by the operation). It also tends to produce confusing compiler diagnostics if one of the arguments is misspelled. [citation needed]

An alternative is:

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

It may be specified this way because the standard does not specify that the internal representation of the null pointer is at address zero. Therefore the difference between the member address and the base address needs to be made.

Some modern compilers (such as GCC) define the macro using a special form (as a language extension) instead, e.g.[3]

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

This builtin is especially useful with C++ classes that declare a custom unary operator &.[4]

Usage edit

It is useful when implementing generic data structures in C. For example, the Linux kernel uses offsetof() to implement container_of(), which allows something like a mixin type to find the structure that contains it:[5]

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

This macro is used to retrieve an enclosing structure from a pointer to a nested element, such as this iteration of a linked list of my_struct objects:

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

The linux kernel implementation of container_of uses a GNU C extension called statement expressions.[6] It's possible a statement expression was used to ensure type safety and therefore eliminate potential accidental bugs. There is, however, a way to implement the same behaviour without using statement expressions while still ensuring type safety:

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

At first glance, this implementation may seem more complex than necessary, and the unusual use of the conditional operator may seem out of place. A simpler implementation is possible:

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

This implementation would also serve the same purpose, however, there's a fundamental omission in terms of the original linux kernel implementation. The type of ptr is never checked against the type of the member, this is something that the linux kernel implementation would catch.

In the aforementioned type-checked implementation, the check is performed by the unusual use of the conditional operator. The constraints of the conditional operator specify that if the operands to the conditional operator are both pointers to a type, they must both be pointers to compatible types. In this case, despite the fact that the value of the third operand of the conditional expression will never be used, the compiler must perform a check to ensure that (ptr) and &((type *)0)->member are both compatible pointer types.

Limitations edit

Usage of offsetof is limited to POD types in C++98, standard-layout classes in C++11,[7] and more cases are conditionally-supported in C++17,[8] otherwise it has an undefined behavior. While most compilers will generate a correct result even in cases that don't respect the standard, there are edge cases when offsetof will either yield an incorrect value, generate a compile-time warning or error, or outright crash the program. This is especially the case for virtual inheritance.[9] The following program will generate several warnings and print obviously suspicious results when compiled with gcc 4.7.3 on an amd64 architecture:

#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 

References edit

  1. ^ "offsetof reference". MSDN. Retrieved 2010-09-19.
  2. ^ "Does &((struct name *)NULL -> b) cause undefined behaviour in C11?". Retrieved 2015-02-07.
  3. ^ "GCC offsetof reference". Free Software Foundation. Retrieved 2010-09-19.
  4. ^ "what is the purpose and return type of the __builtin_offsetof operator?". Retrieved 2012-10-20.
  5. ^ Greg Kroah-Hartman (June 2003). "container_of()". Linux Journal. Retrieved 2010-09-19.
  6. ^ "Statements and Declarations in Expressions". Free Software Foundation. Retrieved 2016-01-01.
  7. ^ "offsetof reference". cplusplus.com. Retrieved 2016-04-01.
  8. ^ "offsetof reference". cppreference.com. Retrieved 2020-07-20.
  9. ^ Steve Jessop (July 2009). "Why can't you use offsetof on non-POD structures in C++?". Stack Overflow. Retrieved 2016-04-01.

offsetof, macro, ansi, library, feature, found, stddef, evaluates, offset, bytes, given, member, within, struct, union, type, expression, type, size, macro, takes, parameters, first, being, structure, union, name, second, being, name, subobject, structure, uni. C s offsetof macro is an ANSI C library feature found in stddef h It evaluates to the offset in bytes of a given member within a struct or union type an expression of type size t The offsetof macro takes two parameters the first being a structure or union name and the second being the name of a subobject of the structure union that is not a bit field It cannot be described as a C prototype 1 Contents 1 Implementation 2 Usage 3 Limitations 4 ReferencesImplementation editThe traditional implementation of the macro relied on the compiler obtaining the offset of a member by specifying a hypothetical structure that begins at address zero define offsetof st m size t amp st 0 gt m This can be understood as taking a null pointer of type structure st and then obtaining the address of member m within said structure While this implementation works correctly in many compilers it has generated some debate regarding whether this is undefined behavior according to the C standard 2 since it appears to involve a dereference of a null pointer although according to the standard section 6 6 Constant Expressions Paragraph 9 the value of the object is not accessed by the operation It also tends to produce confusing compiler diagnostics if one of the arguments is misspelled citation needed An alternative is define offsetof st m size t char amp st 0 gt m char 0 It may be specified this way because the standard does not specify that the internal representation of the null pointer is at address zero Therefore the difference between the member address and the base address needs to be made Some modern compilers such as GCC define the macro using a special form as a language extension instead e g 3 define offsetof st m builtin offsetof st m This builtin is especially useful with C classes that declare a custom unary operator amp 4 Usage editIt is useful when implementing generic data structures in C For example the Linux kernel uses offsetof to implement container of which allows something like a mixin type to find the structure that contains it 5 define container of ptr type member const typeof type 0 gt member mptr ptr type char mptr offsetof type member This macro is used to retrieve an enclosing structure from a pointer to a nested element such as this iteration of a linked list of my struct objects 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 The linux kernel implementation of container of uses a GNU C extension called statement expressions 6 It s possible a statement expression was used to ensure type safety and therefore eliminate potential accidental bugs There is however a way to implement the same behaviour without using statement expressions while still ensuring type safety define container of ptr type member type char 1 ptr amp type 0 gt member offsetof type member At first glance this implementation may seem more complex than necessary and the unusual use of the conditional operator may seem out of place A simpler implementation is possible define container of ptr type member type char ptr offsetof type member This implementation would also serve the same purpose however there s a fundamental omission in terms of the original linux kernel implementation The type of ptr is never checked against the type of the member this is something that the linux kernel implementation would catch In the aforementioned type checked implementation the check is performed by the unusual use of the conditional operator The constraints of the conditional operator specify that if the operands to the conditional operator are both pointers to a type they must both be pointers to compatible types In this case despite the fact that the value of the third operand of the conditional expression will never be used the compiler must perform a check to ensure that ptr and amp type 0 gt member are both compatible pointer types Limitations editUsage of offsetof is limited to POD types in C 98 standard layout classes in C 11 7 and more cases are conditionally supported in C 17 8 otherwise it has an undefined behavior While most compilers will generate a correct result even in cases that don t respect the standard there are edge cases when offsetof will either yield an incorrect value generate a compile time warning or error or outright crash the program This is especially the case for virtual inheritance 9 The following program will generate several warnings and print obviously suspicious results when compiled with gcc 4 7 3 on an amd64 architecture 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 8References edit offsetof reference MSDN Retrieved 2010 09 19 Does amp struct name NULL gt b cause undefined behaviour in C11 Retrieved 2015 02 07 GCC offsetof reference Free Software Foundation Retrieved 2010 09 19 what is the purpose and return type of the builtin offsetof operator Retrieved 2012 10 20 Greg Kroah Hartman June 2003 container of Linux Journal Retrieved 2010 09 19 Statements and Declarations in Expressions Free Software Foundation Retrieved 2016 01 01 offsetof reference cplusplus com Retrieved 2016 04 01 offsetof reference cppreference com Retrieved 2020 07 20 Steve Jessop July 2009 Why can t you use offsetof on non POD structures in C Stack Overflow Retrieved 2016 04 01 Retrieved from https en wikipedia org w index php title Offsetof amp oldid 1220852240, wikipedia, wiki, book, books, library,

article

, read, download, free, free download, mp3, video, mp4, 3gp, jpg, jpeg, gif, png, picture, music, song, movie, book, game, games.