Offsetof: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
No edit summary
SmackBot (talk | contribs)
m Date maintenance tags and general fixes: build 560:
Line 1: Line 1:
{{lowercase}}
{{lowercase}}
C's '''<tt>offsetof</tt>()''' macro is an [[ANSI C]] library feature found in <tt>[[stddef.h]]</tt>. It evaluates to the offset (in bytes) of a given member within a [[struct]] or [[union (computer science)|union]] type, an expression of type <tt>[[size_t]]</tt>. The <tt>offsetof</tt>() macro takes two [[parameters]], the first being a structure name, and the second being the name of a member within the structure. It can not be described as a C prototype.<ref>{{cite web
C's '''<tt>offsetof</tt>()''' macro is an [[ANSI C]] library feature found in <tt>[[stddef.h]]</tt>. It evaluates to the offset (in bytes) of a given member within a [[struct]] or [[union (computer science)|union]] type, an expression of type <tt>[[size t]]</tt>. The <tt>offsetof</tt>() macro takes two [[parameters]], the first being a structure name, and the second being the name of a member within the structure. It can not be described as a C prototype.<ref>{{cite web
| url = http://msdn.microsoft.com/en-us/library/dz4y9b9a.aspx
| url = http://msdn.microsoft.com/en-us/library/dz4y9b9a.aspx
| publisher = [[MSDN]]
| publisher = [[MSDN]]
Line 16: Line 16:
This works by casting a null pointer into a pointer to structure <tt>st</tt>, obtaining the address of member <tt>m</tt> within this structure, casting that address into a character pointer, then using [[pointer arithmetic]] to subtract the base address of the structure, all of which results in the number of character positions (i.e., [[byte]]s) between the beginning of the structure and the beginning of the member.
This works by casting a null pointer into a pointer to structure <tt>st</tt>, obtaining the address of member <tt>m</tt> within this structure, casting that address into a character pointer, then using [[pointer arithmetic]] to subtract the base address of the structure, all of which results in the number of character positions (i.e., [[byte]]s) between the beginning of the structure and the beginning of the member.


While this worked correctly in many historical compilers, it has [[undefined behavior]] according to the C standard, since it involves both a [[dereference]] of a [[null pointer]], and a cast that violates the aliasing rules. Modern compilers will not produce the expected value from this expression{{dubious}}, so a modern <tt>&lt;stddef.h&gt;</tt> is likely to define the macro using a [[special form]] instead, e.g.<ref>{{cite web
While this worked correctly in many historical compilers, it has [[undefined behavior]] according to the C standard, since it involves both a [[dereference]] of a [[null pointer]], and a cast that violates the aliasing rules. Modern compilers will not produce the expected value from this expression{{dubious|date=October 2010}}, so a modern <tt>&lt;stddef.h&gt;</tt> is likely to define the macro using a [[special form]] instead, e.g.<ref>{{cite web
| url = http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Offsetof.html
| url = http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Offsetof.html
| title = GCC offsetof reference
| title = GCC offsetof reference
Line 27: Line 27:


==Usage==
==Usage==
It is useful when implementing generic data structures in C. For example, the [[Linux kernel]] uses <tt>offsetof()</tt> to implement <tt>[[container_of]]()</tt>, which allows something like a [[Mixin]] type to find the structure that contains it:<ref>{{cite web
It is useful when implementing generic data structures in C. For example, the [[Linux kernel]] uses <tt>offsetof()</tt> to implement <tt>[[container of]]()</tt>, which allows something like a [[Mixin]] type to find the structure that contains it:<ref>{{cite web
| url = http://www.kroah.com/log/linux/container_of.html
| url = http://www.kroah.com/log/linux/container_of.html
| title = <tt>container_of()</tt>
| title = <tt>container_of()</tt>

Revision as of 07:44, 31 October 2010

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 name, and the second being the name of a member within the structure. It can not be described as a C prototype.[1]

Implementation

The "traditional" implementation of the macro relied on the compiler being not especially picky about pointers; it obtained the offset of a member by specifying a hypothetical structure that begins at address zero:

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

This works by casting a null pointer into a pointer to structure st, obtaining the address of member m within this structure, casting that address into a character pointer, then using pointer arithmetic to subtract the base address of the structure, all of which results in the number of character positions (i.e., bytes) between the beginning of the structure and the beginning of the member.

While this worked correctly in many historical compilers, it has undefined behavior according to the C standard, since it involves both a dereference of a null pointer, and a cast that violates the aliasing rules. Modern compilers will not produce the expected value from this expression[dubious ], so a modern <stddef.h> is likely to define the macro using a special form instead, e.g.[2]

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

Usage

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:[3]

#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 * iter = /* ... */
while (iter)
{
  struct my_struct * elem = container_of(iter, struct my_struct, list);
  printf("%s\n", elem->name);
  iter = list_next(&elem->list);
}

References

  1. ^ "offsetof reference". MSDN. Retrieved 2010-09-19.
  2. ^ "GCC offsetof reference". Free Software Foundation. Retrieved 2010-09-19.
  3. ^ Greg Kroah-Hartman (2003-06). "container_of()". Linux Journal. Retrieved 2010-09-19. {{cite web}}: Check date values in: |date= (help)