__TRAILING_OVERLAP(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… __TRAILING_OVERLAP (9) β€” Kernel API Manual

okay bestie so this one is from the Kernel API Manual and it's genuinely such a slay little macro, like it's giving "let me hold two things in the same spot" and honestly? iconic. let me walk you through it 🫢


✨ NAME ✨

__TRAILING_OVERLAP β€” overlaps a flexible-array member with trailing members. that's it, that's the whole vibe πŸ’–


✨ SYNOPSIS ✨

__TRAILING_OVERLAP (TYPE , NAME , FAM , ATTRS , MEMBERS );

like yes she takes five things and she makes magic, no cap ✨


🌸 ARGUMENTS 🌸

  • TYPE β€” the flexible structure type name, and yes girl you gotta include the struct keyword, don't forget it or she will NOT know what you mean πŸ™ˆ
  • NAME β€” the name for the variable you're defining, like the name of the actual new thing πŸŽ€
  • FAM β€” the flexible-array member inside TYPE. your fam in the struct sense, your ride-or-die array πŸ’œ
  • ATTRS β€” any struct attributes, and usually this is just empty, like an empty group chat, totally fine πŸ¦‹
  • MEMBERS β€” the trailing overlapping members, the little extras that want to live in the same square footage πŸ‘‘

πŸ”₯ DESCRIPTION πŸ”₯

So what she literally does is: she creates a union between a flexible-array member (that's the FAM, iykyk) in a struct and a set of additional members that would otherwise follow it. two views, one storage, main character energy fr fr πŸ’…

⚠️ okay warning time, bestie, listen to me: because this helper encloses TYPE NAME and MEMBERS in the same union, designated initializers for MEMBERS may overwrite portions you previously initialized through NAME. like they're literally sharing the same lockers and somebody is gonna get their stuff yeeted 😭

For example:

struct flex {
        size_t count;
        u8 fam[];
};

struct composite {
        ...
        __TRAILING_OVERLAP(struct flex, flex, fam, __packed,
                u8 data;
        );
} __packed;

static struct composite comp = {
        .flex = {
                .count = 1,
        },
        .data = 2,
};

In the example above, .flex and .data initialize different views of the same union storage. And since .data is initialized last, it may overwrite portions previously initialized through .flex β€” which can lead to .flex.count being zeroed out. bestie that's your count just... gone. poof. zeroed. πŸ’€

A couple of alternatives are shown below. she gave us options, we love a flexible queen πŸ‘‘

πŸŽ€ a) keep it one-view

Initialize only one view of the overlapped storage and assign the rest at runtime:

static struct composite comp = {
        .flex = {
                .count = 1,
        },
};

static void foo(void)
{
        comp.data = 2;
        ...
}

πŸŽ€ b) runtime assignments only

Alternatively, replace designated initializers with runtime assignments:

static void foo(void)
{
        struct composite comp;

        comp.flex.count = 1;
        comp.data = 2;
        ...
}

Compiler Explorer test code: https://godbolt.org/z/voM4E36dT β€” go poke at it, it's literally right there 🧚

For another example of the above see commit 5e54510a9389 ("acpi: nfit: intel: avoid multiple -Wflex-array-member-not-at-end warnings")

Link: https://git.kernel.org/linus/5e54510a9389caa9


🌈 SEE ALSO 🌈

Kernel file ./include/linux/stddef.h and her whole friend group: sizeof_field(9), offsetofend(9), struct_group(9), struct_group_attr(9), struct_group_tagged(9), DECLARE_FLEX_ARRAY(9), TRAILING_OVERLAP(9) ⭐


and that's the page, bestie!! sign-off time: this gorgeous thing lives over in ./include/linux and the date on it is October 2026 β€” so yeah, she's from the future and she's still serving πŸ’œβœ¨ no cap, go forth and overlap responsibly πŸŽ€

πŸ“¦ where this page comes from