Offsetof
Encyclopedia
C's offsetof macro is an ANSI C
ANSI C
ANSI C refers to the family of successive standards published by the American National Standards Institute for the C programming language. Software developers writing in C are encouraged to conform to the standards, as doing so aids portability between compilers.-History and outlook:The first...

 library feature found in stddef.h. It evaluates to the offset (in bytes) of a given member within a struct
Struct
struct is a computer science term for a record that is used to store more than one value.struct is used in the following programming languages:* struct * struct vs. C++ classes...

 or union
Union (computer science)
In computer science, a union is a value that may have any of several representations or formats; or a data structure that consists of a variable which may hold such a value. Some programming languages support special data types, called union types, to describe such values and variables...

 type, an expression of type size t
Size t
size_t is an unsigned data type defined by several C and C++ standards that is defined in stddef.h. It can be further imported by inclusion of stdlib.h as this file internally sub includes stddef.h....

. 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.

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:
  1. 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., byte
Byte
The byte is a unit of digital information in computing and telecommunications that most commonly consists of eight bits. Historically, a byte was the number of bits used to encode a single character of text in a computer and for this reason it is the basic addressable element in many computer...

s) between the beginning of the structure and the beginning of the member.

While this works correctly in many 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. It also tends to produce confusing compiler diagnostics if one of the arguments is misspelled. Modern compilers often define the macro using a special form instead, e.g.
  1. define offsetof(st, m) __builtin_offsetof(st, m)


Usage

It is useful when implementing generic data structures in C. For example, the Linux kernel
Linux kernel
The Linux kernel is an operating system kernel used by the Linux family of Unix-like operating systems. It is one of the most prominent examples of free and open source software....

 uses offsetof to implement container of, which allows something like a Mixin
Mixin
In object-oriented programming languages, a mixin is a class that provides a certain functionality to be inherited or just reused by a subclass, while not meant for instantiation , Mixins are synonymous functionally with abstract base classes...

type to find the structure that contains it:
  1. 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);
}
The source of this article is wikipedia, the free encyclopedia.  The text of this article is licensed under the GFDL.
 
x
OK