offsetof

From cppreference.com
< c‎ | types
Defined in header <stddef.h>
#define offsetof(type, member) /*implementation-defined*/

The macro offsetof expands to an integer constant expression 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 subobject, including padding if any.

Given an object o of type type with static storage duration, &(o.member) shall be an address constant expression and point to a subobject of o. Otherwise, the behavior is undefined.

If a new type is defined in type, the behavior is undefined.

(since C23)

Notes

If offsetof is applied to a bit-field member, the behavior is undefined, because the address of a bit-field cannot be taken.

member is not restricted to a direct member. It can denote a subobject of a given member, such as an element of an array member.

Even though it is specified in C23 that defining a new type in offsetof is undefined behavior, such usage is only partially supported by implementations even in earlier modes: offsetof(struct Foo { int a; }, a) is usually supported, but offsetof(struct Foo { int a, b; }, a) is not because of the comma in the definition of struct Foo.

Example

#include <stdio.h>
#include <stddef.h>
 
struct S {
    char c;
    double d;
};
 
int main(void)
{
    printf("the first element is at offset %zu\n", offsetof(struct S, c));
    printf("the double is at offset %zu\n", offsetof(struct S, d));
}

Possible output:

the first element is at offset 0
the double is at offset 8

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C standards.

DR Applied to Behavior as published Correct behavior
DR 496 C89 only structs and struct members were mentioned unions and other subobjects are also supported

See also

unsigned integer type returned by the sizeof operator
(typedef)