From: tr.17687@z991.linuxsc.com   
      
   Keith Thompson writes:   
      
   > BGB 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*.   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|