This is something I've sometimes found myself wishing was supported. The
idea being that one can say

unsigned a[] = { [0] = 1, [1] = 3, [0] |= 4, ...}

which would end up initializing a[0] to 5. As a somewhat realistic
example, suppose one is trying to build a bitmap at compile time, but
the bits to set are not really known in the sense that one can group
those belonging to each index in a usual | expression. Something like

#define _(e) [e / 8] |= 1 << (e % 8)
const u8 error_bitmap[] = { _(EINVAL), _(ENAMETOOLONG), _(EBUSY), ... }

Writing a small program to generate such a table as part of the build is
not practical in a cross-compile setting (because the constants may only
really be known to the cross-compiler, e.g. the errno values above).

I think the rules would be rather intuitive: If a compound assignment is
used for an element that doesn't have a previous ordinary initializer,
the LHS is 0. Any later ordinary initializer wipes all previous
operations. No operator precedence; the new value is computed
immediately and used as LHS in subsequent operations.

I'm not sure how to define what happens in unions, but I also don't even
know what the current rules are in a case like

union u { char c; int i; } = { .i = 0x11223344, .c = 0x55 }

where one initializes a smaller member after a larger.

Another issue is how to handle side effects in the RHS. It's probably
consistent with the current behaviour to discard all side effects prior
to the last ordinary initializer, and to do the side effects from all
the expressions that did end up affecting the final value. (Btw., the
current documentation doesn't talk about how this interacts with range
initializers, e.g. [0...5] = x++, [2...6] = y++, [0...4] = z++, does x++
happen?) But for automatic variables, one might as well do the compound
operations in code after the declaration, so it would be fine just
allowing this extension for static initialization.

Rasmus

Reply via email to