Offsetof

Standard macro in the C programming language


title: "Offsetof" type: doc version: 1 created: 2026-02-28 author: "Wikipedia contributors" status: active scope: public tags: ["c-standard-library"] description: "Standard macro in the C programming language" topic_path: "general/c-standard-library" source: "https://en.wikipedia.org/wiki/Offsetof" license: "CC BY-SA 4.0" wikipedia_page_id: 0 wikipedia_revision_id: 0

::summary Standard macro in the C programming language ::

C's **** macro is an ANSI C library feature found in . It evaluates to the offset (in bytes) of a given member within a struct or union type, an expression of type . The 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.{{cite web | url = http://msdn.microsoft.com/en-us/library/dz4y9b9a.aspx | publisher = MSDN | title = offsetof reference | accessdate = 2010-09-19

Implementation

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: ::code[lang=c] #define offsetof(st, m)
((size_t)&(((st*)0)->m)) ::

This can be understood as taking a null pointer of type structure , and then obtaining the address of member 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,{{cite web |url=https://stackoverflow.com/questions/26906621/does-struct-name-null-b-cause-undefined-behaviour-in-c11 |title=Does &((struct name *)NULL - b) cause undefined behaviour in C11? | accessdate = 2015-02-07

An alternative is: ::code[lang=c] #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.{{cite web | url = https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Offsetof.html | title = GCC offsetof reference | publisher = Free Software Foundation | accessdate = 2010-09-19 ::code[lang=c] #define offsetof(st, m)
__builtin_offsetof(st, m) ::

This builtin is especially useful with C++ classes that declare a custom unary .{{cite web | url = https://stackoverflow.com/questions/400116/what-is-the-purpose-and-return-type-of-the-builtin-offsetof-operator/406941#406941 | title = what is the purpose and return type of the __builtin_offsetof operator? | accessdate = 2012-10-20

Usage

It is useful when implementing generic data structures in C. For example, the Linux kernel uses to implement , which allows something like a mixin type to find the structure that contains it:{{cite web | url = http://www.kroah.com/log/linux/container_of.html | title = container_of() | author = Greg Kroah-Hartman | publisher = Linux Journal | date = June 2003 | accessdate = 2010-09-19 ::code[lang=c] #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 objects: ::code[lang=c] struct MyStruct { const char* name; struct ListNode list; };

extern struct ListNode* listNext(struct ListNode*);

struct ListNode* current = /* ... */;

while (current) { struct MyStruct* element = CONTAINER_OF(current, struct MyStruct, list); printf("%s\n", element->name); current = listNext(&element->list); } ::

The Linux kernel implementation of container_of uses a GNU C extension called statement expressions.{{cite web | url = https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html | title = Statements and Declarations in Expressions | publisher = Free Software Foundation | accessdate = 2016-01-01

::code[lang=c] #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:

::code[lang=c] #define CONTAINER_OF(ptr, Type, member) ((Type*)((char*)(ptr) - offsetof(Type, member))) ::

This implementation would also serve the same purpose, however, it has a fundamental omission compared to the original Linux kernel implementation: the type of ptr is never checked against the type of the member.

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

Usage of offsetof is limited to POD types in C++98, standard-layout classes in C++11,{{cite web | url = http://www.cplusplus.com/reference/cstddef/offsetof | title = offsetof reference | website= cplusplus.com | accessdate = 2016-04-01 | url = https://en.cppreference.com/w/cpp/types/offsetof | title = offsetof reference | website= cppreference.com | accessdate = 2020-07-20 | url = https://stackoverflow.com/a/1130760 | title = Why can't you use offsetof on non-POD structures in C++? | author = Steve Jessop | website= Stack Overflow | date = July 2009 | accessdate = 2016-04-01 The following program will generate several warnings and print obviously suspicious results when compiled with gcc 4.7.3 on an amd64 architecture: ::code[lang=c++] #include

import std;

struct Base { int a; virtual void dummy() {} };

struct Derived: virtual public Base { int b; };

int main() { std::println("offsetof(Base, a) : {}", offsetof(Base, a)); std::println("offsetof(Derived, b) : {}", offsetof(Derived, b)); return 0; } ::

Output is: offsetof(Base, a) : 8 offsetof(Derived, b) : 8

References

::callout[type=info title="Wikipedia Source"] This article was imported from Wikipedia and is available under the Creative Commons Attribution-ShareAlike 4.0 License. Content has been adapted to SurfDoc format. Original contributors can be found on the article history page. ::

c-standard-library