offsetof

Bruce Evans bde at zeta.org.au
Fri Apr 1 07:50:34 PST 2005


On Fri, 1 Apr 2005, [iso-8859-1] Dag-Erling Smørgrav wrote:

> I noticed that our definition of offsetof (in <sys/cdefs.h>) is as
> follows:
>
> #define __offsetof(type, field) ((size_t)(&((type *)0)->field))
>
> This definition is gratuitously unportable (it assumes that a null
> pointer is all-bits-zero).  A better definition would be the
> following:
>
> #define __offsetof(type, field) \
>        ((size_t)((char *)&((type *)0)->field - (char *)(type *)0))

Both are unportable, so FreeBSD uses the simplest one.

In fact, the second one is more unportable since it is more complicated.
In both, we don't assume anything about the representation of the null
pointer; we assume that the undefined behaviour for "&((type *)0)->field"
gives a useful value.  This value can be the unrelated to the
representation of "(type *)0", so it can be useful even if "(type *)0"
isn't all-bits-0.  The first version assumes that the useful value is
the final result after further conversions.  The second version assumes
that the undefined behaviour of subtracting a null pointer from the
useful value gives another useful value that is final value after
further conversions.

To be ungratuitously unportable, the definition needs to be machine-
and compiler-dependent.  We don't need the complications for this yet.
It would be mainly compiler-dependent.  Sample definitions:

gcc:
same as FreeBSD except for spelling

TenDRA:
#pragma token PROC { STRUCT s, TYPE t, MEMBER t : s : m |\
    TYPE s, MEMBER s : m } EXP const : size_t : offsetof # ansi.stddef.offsetof

Bruce


More information about the freebsd-standards mailing list