A macro defined in all ISO C (and ISO C++) implementations in the stddef.h header file (or cstddef, in C++...). offsetof(TYPE, MEMBER) takes a struct TYPE (or class, if C++) and the name of a field in that structure. Its value is a size_t giving the number of bytes beyond the start of the structure where that member is stored. Note that C (and C++...) allows padding on structs, so the offset is not just the sum of sizeofs all previous elements in the structure!

For instance, on a machine with 4-byte words, after

#include <stddef.h>

struct x {
  char a[5];
  double b;
  int c;
};
the value of offsetof(struct x, b) might be (and probably is) 8, and the value of offsetof(struct x, c) might be (and probably isn't) 12. offsetof(struct x, a) is always 0 -- see below. Note that offsetof is a macro -- unlike sizeof, which is genuinely recognized by the compiler.

The C standard specifies (elsewhere from the definition of offsetof) that the offsetof the first member of a struct is always 0. But note, in particular, that very little is guaranteed about offsets! In particular, b is the next member after a, but on almost every architecture offsetof(struct x, a)+5 != offsetof(struct x, b), despite the sizeof a being 5. About the only things you can rely on are that offsetofs successive members will be increasing, and that at least the sizeof an element will be allocated before the next element.

It is not possible to define offsetof portably (that's why you get a standard header file defining it for you!). But if stuck without, this code is almost legal C, and will work on most implementations:

#define my_offsetof(type, member)  ((char *)(((type*)NULL)->member)-(char *)NULL)
Just don't complain if it doesn't work -- use the version supplied by your compiler vendor instead.

offsetof isn't often useful, but when needed it can't be beaten. For instance, if you need to read or write part of a struct, you'll need to use offsetof in conjuction with sizeof.

Log in or register to write something here or to contact authors.