You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
offsetof(type, member-designator)
which expands to an integer constant expression that has type size_t, the value of
which is the offset in bytes, to the structure member (designated by member-designator),
from the beginning of its structure (designated by 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.
Note the "integer constant" and "address constant" clauses. I don't think this condition is met in your example. So, I think CompCert is not wrong to reject it. But it is surprising indeed, since the naive implementation of offsetof(ty, memb) as
(size_t) (char *) (((ty *) NULL)->memb)
seems to work even if memb contains a non-constant array reference.
is undefined behavior, though I guess if a compiler knows it won't exploit that UB it is free to define offsetof that way, and that the approach hinted at by the standard, where we consider the address of the designated member of a statically allocated object, would also involve undefined behavior if someNumber * sizeof(Element) is greater than sizeof(Container) - offsetof(Container, items), which I'm fairly certain means it is defined only for someNumber == 0 (given the specific structs above).
Now it would be really nice to change this, but I think that either requires the spec to hypothesize a magic builtin just for this, or to hand-wave away the array-indexing rules somehow, because there is no way to get a suitable object to use to form a pointer to arbitrary flexible-array items: to even know how big the object would be, you would need offsetof ...
Now GCC has a builtin for offsetof, but it's not clear that it allows arbitrary flexible array indexing.
So it's probably tricky to actually change the standard to allow this :-(.
Activity
xavierleroy commentedon May 6, 2025
That's an interesting edge case, indeed !
The C11 standard says:
Note the "integer constant" and "address constant" clauses. I don't think this condition is met in your example. So, I think CompCert is not wrong to reject it. But it is surprising indeed, since the naive implementation of
offsetof(ty, memb)asseems to work even if
membcontains a non-constant array reference.SamB commentedon Mar 9, 2026
... yeah, arguably the standard should only require
for the expansion to be an integer constant expression.
But I'm pretty sure that the implementation
is undefined behavior, though I guess if a compiler knows it won't exploit that UB it is free to define
offsetofthat way, and that the approach hinted at by the standard, where we consider the address of the designated member of a statically allocated object, would also involve undefined behavior ifsomeNumber * sizeof(Element)is greater thansizeof(Container) - offsetof(Container, items), which I'm fairly certain means it is defined only forsomeNumber == 0(given the specific structs above).Now it would be really nice to change this, but I think that either requires the spec to hypothesize a magic builtin just for this, or to hand-wave away the array-indexing rules somehow, because there is no way to get a suitable object to use to form a pointer to arbitrary flexible-array items: to even know how big the object would be, you would need
offsetof...Now GCC has a builtin for
offsetof, but it's not clear that it allows arbitrary flexible array indexing.So it's probably tricky to actually change the standard to allow this :-(.