• Re: Nice way of allocating flexible struct.

    From Tim Rentsch@3:633/10 to All on Mon Dec 15 11:24:29 2025
    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)
  • From Tim Rentsch@3:633/10 to All on Tue Jan 6 18:24:27 2026
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    bart <bc@freeuk.com> writes:

    On 09/10/2025 04:49, BGB wrote:

    [...]

    Nobody cares about C syntax.

    That is so manifestly untrue that I can't imagine what you actually
    meant.

    Many of us, myself included, don't particularly like some aspects of
    C syntax, but that's not the same as not caring about it.

    Learning all its ins and outs seems be
    a rite of passage.

    Perhaps. It's also necessary if you want to work with the language.

    The trouble is that C-style is so dominant, few people would know
    what a decent syntax looks like. Or, more, likely, they associate
    a clean, well-designed syntax with toy or scripting languages, and
    can't take it seriously.

    But if it looks as hairy as C++ then it must be the business!

    C syntax has survived and been propagated to other languages because
    it's well known, not, I think, because anybody really likes it.

    I like C syntax, most of it anyway. Even the parts I don't
    especially like aren't horrendous, which is more than I can
    say for some other popular languages.

    --- PyGate Linux v1.5.2
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)