The offsetof macro is an ANSI C library feature defined in <stddef.h> that evaluates to the offset in bytes of a specified member within a struct or union type, returned as a value of type size_t. It takes two parameters: the structure or union type and the name of the member (which cannot be a bit-field), allowing developers to calculate the displacement of a field from the beginning of the object, including any padding inserted by the compiler.

Commonly used for implementing generic data structures and serialization, offsetof is essential in C for patterns like container_of, which retrieves a pointer to an enclosing structure from a pointer to one of its members. A typical implementation relies on pointer arithmetic with a null pointer:

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

While this works on many compilers, the C standard defines it as an integral constant expression, and modern compilers like GCC often use built-in extensions like __builtin_offsetof for better safety and diagnostics.

Key Characteristics and Limitations

  • Usage: It calculates the byte offset of a member, which is not necessarily the sum of previous member sizes due to alignment and padding.

  • C++ Constraints: In C++, offsetof is restricted to POD types (pre-C++11), standard-layout types (C++11 and later), or conditionally-supported cases (C++17); using it with virtual inheritance or non-standard-layout classes results in undefined behavior.

  • Restrictions: The macro cannot be applied to bit-fields, static data members, or member functions, and the member must be a subobject of the type.

  • Portability: Although the traditional null-pointer dereference method is widely used, it can be considered undefined behavior by the strictest interpretations of the C standard, leading some implementations to use compiler-specific intrinsics.

Standard macro in the C programming language
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 … Wikipedia
🌐
Wikipedia
en.wikipedia.org › wiki › Offsetof
offsetof - Wikipedia
October 29, 2025 - 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 ...
🌐
Cppreference
en.cppreference.com › w › cpp › types › offsetof.html
offsetof - cppreference.com
March 26, 2024 - The macro offsetof expands to an integral constant expression of type std::size_t, the value of which is the offset, in bytes, from the beginning of an object of specified type to its specified subobject, including padding bits if any.
🌐
TutorialsPoint
tutorialspoint.com › c_standard_library › c_macro_offsetof.htm
C library - offsetof() macro
The C library offsetof(type, member-designator) Macro results in a constant integer of type size_t which is the offset in bytes of a structure member from the beginning of the structure.
Top answer
1 of 4
51

R.. is correct in his answer to the second part of your question: this code is not advised when using a modern C compiler.

But to answer the first part of your question, what this is actually doing is:

(
  (int)(         // 4.
    &( (         // 3.
      (a*)(0)    // 1.
     )->b )      // 2.
  )
)

Working from the inside out, this is ...

  1. Casting the value zero to the struct pointer type a*
  2. Getting the struct field b of this (illegally placed) struct object
  3. Getting the address of this b field
  4. Casting the address to an int

Conceptually this is placing a struct object at memory address zero and then finding out at what the address of a particular field is. This could allow you to figure out the offsets in memory of each field in a struct so you could write your own serializers and deserializers to convert structs to and from byte arrays.

Of course if you would actually dereference a zero pointer your program would crash, but actually everything happens in the compiler and no actual zero pointer is dereferenced at runtime.

In most of the original systems that C ran on the size of an int was 32 bits and was the same as a pointer, so this actually worked.

2 of 4
21

It has no advantages and should not be used, since it invokes undefined behavior (and uses the wrong type - int instead of size_t).

The C standard defines an offsetof macro in stddef.h which actually works, for cases where you need the offset of an element in a structure, such as:

#include <stddef.h>

struct foo {
    int a;
    int b;
    char *c;
};

struct struct_desc {
    const char *name;
    int type;
    size_t off;
};

static const struct struct_desc foo_desc[] = {
    { "a", INT, offsetof(struct foo, a) },
    { "b", INT, offsetof(struct foo, b) },
    { "c", CHARPTR, offsetof(struct foo, c) },
};

which would let you programmatically fill the fields of a struct foo by name, e.g. when reading a JSON file.

🌐
The Coding Forums
thecodingforums.com › archive › archive › c programming
Uses of offsetof? | C Programming | Coding Forums
March 26, 2007 - Since &a is of type (struct s *), ... you expect. One use of offsetof() is to effectively pass around a member of a structure, when *which* member it is is not known at compile time....
🌐
Linuxcampus
linuxcampus.net › documentation › man-html › htmlman3 › offsetof.3.html
offsetof(3) — Linux manual pages
#include <stddef.h> #include <stdio.h> #include <stdlib.h> int main(void) { struct s { int i; char c; double d; char a[]; }; /* Output is compiler dependent */ printf("offsets: i=%zu; c=%zu; d=%zu a=%zu\n", offsetof(struct s, i), offsetof(struct s, c), offsetof(struct s, d), offsetof(struct s, a)); printf("sizeof(struct s)=%zu\n", sizeof(struct s)); exit(EXIT_SUCCESS); }
🌐
Open-std
open-std.org › jtc1 › sc22 › wg21 › docs › papers › 2024 › p3407r0.html
Make idiomatic usage of `offsetof` well-defined
October 14, 2024 - In C, the offsetof macro is frequently used to obtain a pointer to an object given a pointer to one of its subobjects. Such C code is often incompatible with C++ because of two changes to the pointer provenance model made in C++17.
Find elsewhere
🌐
GNU
gcc.gnu.org › onlinedocs › gcc-4.1.0 › gcc › Offsetof.html
Offsetof - Using the GNU Compiler Collection (GCC)
primary: "__builtin_offsetof" "(" typename "," offsetof_member_designator ")" offsetof_member_designator: identifier | offsetof_member_designator "." identifier | offsetof_member_designator "[" expr "]"
🌐
University of Chicago
naipc.uchicago.edu › 2014 › ref › cppreference › en › c › types › offsetof.html
offsetof - cppreference.com
The macro offsetof expands to a constant of type size_t, the value of which is the offset, in bytes, from the beginning of an object of specified type to its specified member, including padding if any.
🌐
GeeksforGeeks
geeksforgeeks.org › c++ › the-offsetof-macro
The OFFSETOF() macro - GeeksforGeeks
July 23, 2025 - For example, the following code returns 16 bytes (padding is considered on 32 bit machine) as displacement of the character variable c in the structure Pod. ... #include <iostream> using namespace std; #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) typedef struct PodTag { int i; double d; char c; } PodType; int main() { cout << OFFSETOF(PodType, c); return 0; } // This code is contributed by sarajadhav12052009
🌐
Linux Man Pages
linux.die.net › man › 3 › offsetof
offsetof(3): offset of structure member - Linux man page
#include <stddef.h> #include <stdio.h> #include <stdlib.h> int main(void) { struct s { int i; char c; double d; char a[]; }; /* Output is compiler dependent */ printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n", (long) offsetof(struct s, i), (long) offsetof(struct s, c), (long) offsetof(struct s, d), (long) offsetof(struct s, a)); printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s)); exit(EXIT_SUCCESS); }
🌐
GitHub
gist.github.com › graphitemaster › 494f21190bb2c63c5516
Working around offsetof limitations in C++ · GitHub
But I found that the diagnostics for that were less legible than not having any check at all. ... This only yields enough memory for x, there'll be no room for y - there will just be 4 bytes available as the offset of y is 4. ... offsetof's behavior is undefined because standard does not guarantee that z will lay after y.
🌐
Linux Man Pages
man7.org › linux › man-pages › man3 › offsetof.3.html
offsetof(3) - Linux manual page
On a Linux/i386 system, when compiled using the default gcc(1) options, the program below produces the following output: $ ./a.out offsets: i=0; c=4; d=8 a=16 sizeof(struct s)=16 Program source #include <stddef.h> #include <stdio.h> #include <stdlib.h> int main(void) { struct s { int i; char c; double d; char a[]; }; /* Output is compiler dependent */ printf("offsets: i=%zu; c=%zu; d=%zu a=%zu\n", offsetof(struct s, i), offsetof(struct s, c), offsetof(struct s, d), offsetof(struct s, a)); printf("sizeof(struct s)=%zu\n", sizeof(struct s)); exit(EXIT_SUCCESS); }
🌐
Barr Group
barrgroup.com › blog › how-use-cs-offsetof-macro
How to Use C's offsetof() Macro
March 1, 2004 - Simply put, the offsetof() macro returns the number of bytes of offset before a particular element of a struct or union. The declaration of the macro varies from vendor to vendor and depends upon the processor architecture. Browsing through the compilers on my computer, I found the example ...
🌐
C-faq
c-faq.com › struct › offsetof.html
Question 2.14
A: ANSI C defines the offsetof() macro in <stddef.h>, which lets you compute the offset of field f in struct s as offsetof(struct s, f).
🌐
Embarcadero
docwiki.embarcadero.com › RADStudio › en › Offsetof
offsetof - RAD Studio
offsetof returns the number of bytes from the start of the structure to the start of the named structure member. ... #include <stddef.h> struct fill_struct { int _f1, _f2, _f3; char* _str; }; int _tmain(int argc, _TCHAR* argv[]) { printf("The _str member of fill_struct starts at offset %d", ...
🌐
UrbanPro
urbanpro.com › c++ language › learn advanced c++
Magic in C => OFFSET OF MACRO in C - UrbanPro
May 20, 2019 - typedef struct { int i; float f; char c; } SFOO; void main(void) { printf("Offset of 'f' is %u", offsetof(SFOO, f)); } #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 1 Like 0 Dislike · Follow 3 · C Programming Introduction · Beginners: C Programming is the base of all programming languages we learn.
🌐
Microsoft Learn
learn.microsoft.com › en-us › cpp › c-runtime-library › reference › offsetof-macro
offsetof Macro | Microsoft Learn
October 26, 2022 - The offsetof macro returns the offset in bytes of memberName from the beginning of the structure specified by structName as a value of type size_t. You can specify types with the struct keyword.
🌐
SAS
support.sas.com › documentation › onlinedoc › sasc › doc750 › html › lr1 › znid-159.htm
Introduction to the SAS/C Library : offsetof
The offsetof macro provides the decimal byte offset of a component within a structure as a size_t constant. This constant is generated at compile time. Padding for alignment, if any, is included. The operands of offsetof are a structure type ( type ) and a component of the structure specification ...