Unfortunately, ISO C requires offsetof to calculate a constant; moreover, the right operand is a "member designator", which elements[N] isn't.
However, the traditional (and pretty much the only sensible) ways of defining offsetof do make it work.
N3220 draft:
offsetof(type, member-designator)
[expands] to an integer constant expression that has type size_t, the value of which is the
offset in bytes, to the subobject (designated by member-designator), from the beginning of any object
of type type. The type and member designator shall be such that given
static type t;
then the expression &(t. member-designator) evaluates to an address constant. If the specified type
name contains a comma not between matching parentheses or if the specified member is a bit-field,
the behavior is undefined.
This doesn't mean I won't use it, but just something to be aware of.
It might not be a bad idea to propose to ISO C that offsetof(type, array[n]) should be required to work, and for non-constant n too.
In GCC, __builtint_offsetof explicitly supports the extended syntax for the member designator. when the offsetof macro uses __builtin_offsetof, the capability is a documented extension.
However, the traditional (and pretty much the only sensible) ways of defining offsetof do make it work.
N3220 draft:
[expands] to an integer constant expression that has type size_t, the value of which is the offset in bytes, to the subobject (designated by member-designator), from the beginning of any object of type type. The type and member designator shall be such that given then the expression &(t. member-designator) evaluates to an address constant. If the specified type name contains a comma not between matching parentheses or if the specified member is a bit-field, the behavior is undefined.This doesn't mean I won't use it, but just something to be aware of.
It might not be a bad idea to propose to ISO C that offsetof(type, array[n]) should be required to work, and for non-constant n too.