Path: csiph.com!pasdenom.info!newsfeed.bofh.team!eternal-september.org!feeder.eternal-september.org!nntp.eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch
Newsgroups: comp.lang.c
Subject: Re: Are designated initializer supposed to zero padding?
Date: Sun, 10 May 2026 20:01:53 -0700
Organization: A noiseless patient Spider
Lines: 95
Message-ID: <86jytar6n2.fsf@linuxsc.com>
References: <10tqqso$kn23$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Date: Mon, 11 May 2026 03:01:55 +0000 (UTC)
Injection-Info: dont-email.me; logging-data="879687"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX198ReSNZ/w0mwybTpZZ/6FUfROAewEW/Zc="; posting-host="e12ff559fd79fb3307443db8d47ea871"
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:W2ZnSklvwao1P5gMXNE9Mrpi2d8= sha1:wJqAflw1no8N7Blv9KSkmY10aXs= sha256:J0RK/IvvWQFHkhqCbowrsnb3iHcdGg+pQw4qO7/+KiU= sha1:SYnpF8buizeprei+r1g2Ur1tSXw=
Xref: csiph.com comp.lang.c:398700
highcrew writes:
> Hello,
>
> I recently wrote a unit test, where I'm verifying that some array
> of data matches the expected value. The comparison is done by looping
> on individual items, and invoking a comparison function for each of
> them.
>
> struct item { long a, b; in c; };
> struct array { unsigned int n; struct item a[] }; // FAM
>
> const struct item expected[] = {
> {1, 2, 3},
> {4, 5, 6},
> };
>
> struct array *actual = get(); // using calloc under the hood
> assert(compare_array(expected, ARRSIZE(expected), actual) == 0);
> free(actual);
>
> Oh, and I cheated on the comparison, thinking I could get away with a
> memcmp():
>
> int compare(const struct item *a, const struct item *b)
> {
> return memcmp(a, b, sizeof *a);
> }
>
> This test worked as intended under Debian (gcc 14.2.0), and failed under
> Alpine Linux (gcc 15.2.0. But it works with clang).
>
> Why? Because the padding of course. It is OK in the `actual`
> array thanks to the fact I'm using `calloc()` under the hood, but it is
> not zero-initialized in `expected`, declared on the stack.
> The clean solution: don't cheat nor assume padding is zeroed out, and
> write a proper comparison function.
>
> ...
>
> But then I started to wonder: isn't a designated initializer
> supposed to wipe the memory? I definitely seen that happen, but
> this is of course not saying it *must* happen.
>
> I can't find anything in the standard (I checked N3220). I
> only found a mention of static and thread local objects, but
> nothing about objects declared on the stack.
>
> So, is the compiler only required to clear individual fields?
> Can it leave dirty memory on padding? Or did I hit a compiler
> bug?
You seem to be asking two different questions, one about padding
and one about flexible array members. The example code is
incomplete, so it's hard to be sure exactly what your questions
are, but let me take a stab at being helpful.
Point 1: initializers are not required to set padding (either
padding bits or padding bytes). Don't expect padding to be
zeroed. This statement applies to initializers in all forms -
regular initializers, designated initializers, and compound
literals.
Point 2: flexible array members do not participate in any
initialization. Usually it's a mistake to declare a struct with a
flexible array member as an ordinary variable, but in any case there
is no way to use a declaration of a struct-with-fam to initialize
elements of the flexible array member.
Point 3: if you want to initialize and zero a struct, along with
elements of a non-trivial flexible array member, probably the best
way to do that is as part of a union with an array of unsigned char,
for example as follows:
union {
unsigned char uca[ SUITABLE_SIZE ];
struct array fam;
} blah = { .uca = { 0 } };
struct array *stuff = &blah.fam;
after which the variable 'stuff' can be used to refer to the zeroed
struct-with-flexible-array-member. These two pieces can be combined
into one, like so:
struct array *stuff =
&(union {
unsigned char uca[ SUITABLE_SIZE ];
struct array fam;
}){ .uca = { 0 } }.fam;
assuming I haven't made any mistakes in transcription.
Admittedly this is ugly but maybe it can be used to accomplish
what you want.