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.