fnf@mcdsun.UUCP (Fred Fish) (08/11/87)
The following possible bug report was generated due in part to failure to compile code from a compiler test suite. I'd like to solicit opinions on whether or not the code is valid pre-ANSI C, valid ANSI C, or not valid C. Note also that Harbison and Steele go into a little more detail than the draft ANSI standard, and also introduce the notion that the "shape" of the initializers should match the "shape" of the object being initialized, which in this case I would take to mean that a valid initializer would be of the form "{{a,b},{c,d}}". -Fred /* * Possible structure initialization bug (see comments below). * Results from various compilers are: * * GNU C compiler: No complaint. * bar.foo[0][0] = 1; * bar.foo[0][1] = 2; * bar.foo[1][0] = 3; * bar.foo[1][1] = 4; * * SUN 3.2 C compiler: complains about '}' expected * (pcc based) bar.foo[0][0] = 1; * bar.foo[0][1] = 2; * bar.foo[1][0] = 0; * bar.foo[1][1] = 0; * * Motorola 68020 cc complains about '}' expected * (pcc based) bar.foo[0][0] = 1; * bar.foo[0][1] = 2; * bar.foo[1][0] = 0; * bar.foo[1][1] = 0; * * Greenhills 68020 cc complains about initializer too large * no output file generated. * * The draft ANSI C standard is quite specific about the * behavior when there are too few initializers for an * aggregate or subaggregate, but doesn't really address * the reverse situation of too many initializers (that I could * find anyway). Section 3.5.6 has this to say: * * "There shall be no more initializers in an initializer list than * there are objects to be initialized." Well, I see four objects * to initialize and four initializers, so read on... * * "... the initializer for an object that has aggregate type shall * be a brace-enclosed list of initializers for the members of the * aggregate, wirttin in increasing subscript or member order. If the * aggregate contains members that are aggregates, the rules apply * recursively to the subaggregates. If the initializer of a sub- * aggregate begins with a left brace, the succeeding initializers * initialize the members of the subaggregate. Otherwise, only * enough initializers from the list are taken to account for the * members of the first subaggregate; any remaining initializers * are left to initialize the next member of the subaggregate of * which the current aggregate is a part." * */ struct { int foo[2][2]; } bar = { {1, 2, 3, 4} }; main () { printf ("bar.foo[0][0] = %d\n", bar.foo[0][0]); printf ("bar.foo[0][1] = %d\n", bar.foo[0][1]); printf ("bar.foo[1][0] = %d\n", bar.foo[1][0]); printf ("bar.foo[1][1] = %d\n", bar.foo[1][1]); } -- = Drug tests; just say *NO*! = Fred Fish Motorola Computer Division, 3013 S 52nd St, Tempe, Az 85282 USA = seismo!noao!mcdsun!fnf (602) 438-3614
gwyn@brl-smoke.ARPA (Doug Gwyn ) (08/12/87)
In article <352@mcdsun.UUCP> fnf@mcdsun.UUCP (Fred Fish) writes: >I'd like to solicit opinions on whether or not the code is valid pre-ANSI >C, valid ANSI C, or not valid C. >struct { > int foo[2][2]; >} bar = { > {1, 2, 3, 4} >}; It's obviously not valid C -- you have provided 4 initializers in the list for the object bar.foo[0], but that object is an aggregate that only has two elements, bar.foo[0][0] and bar.foo[0][1]. What was probably intended should be written: struct { int foo[2][2]; } bar = { {1, 2}, {3, 4}, /* comma optional */ }; Note that many existing compilers are overly permissive on this, and that the intent of ANSI C will be to provide sane semantics for the use of EITHER fully-bracketed initializer lists OR completely unbracketed lists, with consistent but not necessarily sane rules for the intermediate cases -- which we hope nobody will ever be so foolish as to use. A couple of X3J11 meetings ago, Dave Prosser and I independently worked through the rules for an incompletely-bracketed case, and came up with the same answer, as well as a conviction that the rules were complete and consistent. One or two other people agreed with us, and most of the rest seemed as bewildered by the initializer bracketing rules as I recently was by the lvalueness rules.
drew@geac.UUCP (Drew Sullivan) (08/13/87)
Microsoft C, version 4.0 took the program without complaint and returned: bar.foo[0][0] = 1 bar.foo[0][1] = 2 bar.foo[1][0] = 3 bar.foo[1][1] = 4 -- Drew Sullivan <drew@lethe.uucp>
drw@cullvax.UUCP (Dale Worley) (08/13/87)
fnf@mcdsun.UUCP (Fred Fish) writes:
# [Is the following construction valid?]
#
# struct {
# int foo[2][2];
# } bar = {
# {1, 2, 3, 4}
# };
#
# [Notes that the initializer "{{1, 2}, {3, 4}}" is
# preferred for portability in pre-ANSI systems.]
# [The following is from 3.5.6 of the Draft:]
# * "... the initializer for an object that has aggregate type shall
# * be a brace-enclosed list of initializers for the members of the
# * aggregate, written in increasing subscript or member order. If the
# * aggregate contains members that are aggregates, the rules apply
# * recursively to the subaggregates. If the initializer of a sub-
# * aggregate begins with a left brace, the succeeding initializers
# * initialize the members of the subaggregate. Otherwise, only
# * enough initializers from the list are taken to account for the
# * members of the first subaggregate; any remaining initializers
# * are left to initialize the next member of the subaggregate of
# * which the current aggregate is a part."
It seems to be that the last clause has a typo; it should read "...the
next member of the *aggregate* of which the current *subaggregate* is
a part". Otherwise it doesn't make sense.
My reading is that if a subaggregate initializer (in this case, for
the two subordinate arrays) doesn't start off with a '{', then it just
draws the proper number of elements from the list and the remainder of
the list initializes elements of the top-level aggregate.
What you wrote should work, because you are initializing a "structure
with a field which is an array of arrays of integers". The
initializers break down:
object initializer
bar { { 1, 2, 3, 4 } }
bar.foo { 1, 2, 3, 4 }
At this point, we invoke the "if the initializer for a subaggregate
does not begin with a left brace rule", and the elements bar.foo[*][*]
get initialized like you'd expect.
Dale
--
Dale Worley Cullinet Software ARPA: cullvax!drw@eddie.mit.edu
UUCP: ...!seismo!harvard!mit-eddie!cullvax!drw
OS/2: Yesterday's software tomorrow Nuclear war? There goes my career!
gwyn@brl-smoke.ARPA (Doug Gwyn ) (08/15/87)
In article <353@mcdsun.UUCP> fnf@mcdsun.UUCP (Fred Fish) writes: >I should probably have noted in the original posting that the reason >this question came up, what that there was similar code (with lots >more dimensions and lots more brackets) in a commercial compiler test >suite that I am entangled in at the moment. ... Well, it sounds like the test suite is trying to test dark corners of the language where it was never clear what was "right". I know of three commercial C compiler test suites, and they each try to test a different "flavor" of C (one of them comes in a couple of flavors). Obviously, none of them can yet test against the ANSI standard for C, which will be the most meaningful reference point in the near future. >... Most of the problems appear to be generic pcc type bugs. Certainly PCC (in its various versions) has had lots of bugs and strange ideas what the language rules were. Some test suites actually check for conformance to PCC's idea of the language! (K&R Appendix A is the other popular reference point.)
peter@sugar.UUCP (Peter da Silva) (08/16/87)
int x[2][2] = { 1, 2, 3, 4 }; I believe Ritchie's compiler (and other old 'C' compilers) treated nested parentheses in aggregate initialisations as informative only, to be used when ambiguities were found or subelements weren't fully initialised. For example: int x[2][2] = { 1, 2 } == { {1, 2}, {0, 0} }; 1 2 0 0 int x[2][2] = { {1}, {2} } == { {1, 0} {2, 0} }; 1 0 2 0 -- -- Peter da Silva `-_-' ...!seismo!soma!uhnix1!sugar!peter (I said, NO PHOTOS!)
michaud@decvax.UUCP (Jeff Michaud) (08/18/87)
What you really want is: struct { int foo[2][2]; } xyz = { 1, 2, 3, 4 }; Notice only a depth of 1 on the {} nesting.
brianc@cognos.uucp (Brian Campbell) (08/19/87)
In article <352@mcdsun.UUCP> fnf@mcdsun.UUCP (Fred Fish) writes: > [ question as to whether following is valid initialization ] > struct { > int foo[2][2]; > } bar = { > {1, 2, 3, 4} > }; Is this really a *struct* initialization question, or a two- dimensional array initialization question? According to K&R (Sec. 5.7): "An array is initialized by a list of initializers in braces; each row of a two-dimensional array is initialized by a corresponding sub-list." -- Brian Campbell uucp: decvax!utzoo!dciem!nrcaer!cognos!brianc Cognos Incorporated mail: 3755 Riverside Drive, Ottawa, Ontario, K1G 3N3 (613) 738-1440 fido: sysop@163/8
fnf@mcdsun.uucp (Fred Fish) (08/20/87)
In article <6277@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >In article <352@mcdsun.UUCP> fnf@mcdsun.UUCP (Fred Fish) writes: >[..deleted..] >What was probably intended should be written: >[..deleted..] >completely unbracketed lists, with consistent but not necessarily >sane rules for the intermediate cases -- which we hope nobody will >ever be so foolish as to use. I should probably have noted in the original posting that the reason this question came up, what that there was similar code (with lots more dimensions and lots more brackets) in a commercial compiler test suite that I am entangled in at the moment. Naturally, I cannot post the relevant test code, but I believe my distillation of the code that triggered a possible bug is correct. It is obvious that the compiler test suite is trying to test the bounds of the initialization rules, as there are lots and lots of different permutations of partially bracketed lists. By the way, this same test suite has turned up over a dozen bugs in the native Sun 3.2 C compiler and the Motorola 68020 C compiler and I've only just recently finished running the first of many parts of the suite. Most of the problems appear to be generic pcc type bugs. -Fred -- = Drug tests; just say *NO*! = Fred Fish Motorola Computer Division, 3013 S 52nd St, Tempe, Az 85282 USA = seismo!noao!mcdsun!fnf (602) 438-3614
gwyn@brl-smoke.ARPA (Doug Gwyn ) (08/23/87)
In article <1287@cognos.UUCP> brianc@cognos.UUCP (Brian Campbell) writes: > Is this really a *struct* initialization question, or a two- >dimensional array initialization question? According to current notions, it'a an AGGREGATE initialization question.