Multi-dimensional array initialization
Curt Wohlgemuth
curtw at hpcllca.HP.COM
Tue Jun 13 06:15:19 AEST 1989
schmidt at siam.ics.uci.edu (Doug Schmidt) writes:
> Consider the following 2-dimensional array declaration:
>
> ----------------------------------------
> typedef struct { int i; int j; } bar;
>
> static bar foo[4][4]; /* 4 * 4 == 16 element array of `bar's. */
> ----------------------------------------
>
> Now, let's assume that this array is given 16 initial values instead:
>
> ----------------------------------------
> typedef struct { int i; int j; } bar;
>
> static bar foo[4][4] =
> {
> { {1,0}, {2,0}, {3,0}, {4,0}, },
> { {5,0}, {6,0}, {7,0}, {8,0}, },
> { {9,0}, {10,0}, {11,0}, {12,0}, },
> {{13,0}, {14,0}, {15,0}, {16,0}, },
> };
In this example, all of the braces for the initializer are specified;
none are elided. Every compiler should properly initialize 'foo' in the
same manner here.
> Now, suppose that we leave out the explicit curly braces that demarcate rows,
> i.e., certain '{' and '}':
I.e., you want to partially elide the braces for the initializer for 'foo' --
a dangerous action!
> ----------------------------------------
> static bar foo[4][4] =
> {
> {1,0}, {2,0}, {3,0}, {4,0}, {5,0}, {6,0}, {7,0}, {8,0},
> {9,0}, {10,0}, {11,0}, {12,0}, {13,0}, {14,0}, {15,0}, {16,0},
> };
> ----------------------------------------
>
> Can someone please tell me which version is *correct* w.r.t.
>
> 1. The latest ANSI-C draft.
The December '88 draft standard (and I assume this is unchanged) says (3.5.7):
"If the initializer of a subaggregate or contained union begins
with a left brace, the initializers enclosed by that brace and
its matching right brace initialize the members of the
subaggregate or the first member of the contained union."
In the second example above, according to the (d)pANS then, the first '{'
begins the initializer for 'foo'. The next '{' begins the initializer for
the first subaggregate for 'foo': namely, 'foo[0]'.
So we have a sub-problem: '{1,0}' initializes 'foo[0]', _in its entirety_.
Similarly, '{2,0}' initializes 'foo[1]', '{3,0}' initializes 'foo[2]',
and '{4,0}' initializes 'foo[3]'.
Now the compiler sees '{5,0}', but it has run out of storage to fill
(it tries to put it into 'foo[5]'). Hence some kind of diagnostic
for "too many initializers".
All of this is because you elided some braces in the initializer. Had you
left them in (as in the first example), then
'{ {1,0}, {2,0}, {3,0}, {4,0} }'
would be the total initializer for 'foo[0]', and you would get what you want.
Similarly, if you elide _all_ the braces (except the outermost) in the
initializer, you will also get what you desire.
> 2. Traditional behavior on UNIX compilers.
Typically, pcc-based compilers seem to parse brace-enclosed initializers
in a bottom-up fashion. ANSI specifies that it must be done in a top-down
manner (which, I believe, K&R intended also). Hence the discrepency you
observe.
More information about the Comp.lang.c
mailing list