Keith Thompson <
Keith.S.Thompson+u@gmail.com> writes:
BGB <cr88192@gmail.com> writes:
On 10/8/2025 1:35 AM, Kaz Kylheku wrote:
Jonas Lund of https://whizzter.woorlic.org/ mentioned this
trick in a HackerNews comment:
Given:
struct S {
// ...
T A[];
};
Don't do this:
malloc(offsetof(S, A) + n * sizeof (T));
But rather this:
malloc(offsetof(S, A[n]));
It's easy to forget that the second argument of offsetof is a
designator, not simply a member name.
This is assuming offsetof and can deal with general expressions (vs
just field names). IIRC, it is only required to work with field names
(and with plain structs).
I just read that part of the standard, and it's not clear whether
the second argument to offsetof() has to be a member name or whether
it can be something more elaborate.
Quoting the N3096 draft of C23, 7.21:
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
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* defines a new
type or if the specified member is a bit-field, the behavior
is undefined.
The requirements imply that the type can be a struct or a union.
The term "member designator" is not used elsewhere in the standard.
If the term to be taken literally, then it has to designate a
*member*, not an element of a member. But the term "subobject",
along with the address constant requirement, could imply that it
could be an arbitrary sequence of members and array elements.
Clearly the italicized token member-designator is just a placeholder
with no semantics implied, and the controlling text here is the word "subobject", which applies recursively.
Note also that the phrase "from the beginning of any object of type
*type*" precludes the use of 'offsetof(S, A[n])', if n is too large,
since A[n] will not be a subobject of an arbitrary object of type
*type*.
--- PyGate Linux v1.5.2
* Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)