jeapedai@pttesac.UUCP (J. E. Apedaile) (01/23/90)
The example code that follows compiles correctly and prints the right values when executed on SunOS 4.0.3 and on a UNIX-PC OS 3.5 (SVR2.?). The code that this was taken from also compiled without error on an AT&T SVR2.2 compiler. Gcc on the UNIX-PC gives the following warning and output: jim 57 > gcc e.c e.c: In function main: e.c:21: warning: excess elements in aggregate initializer jim 58 > a.out 40, cf000, ff000 0, 0, 0 0, 0, 0 0, 0, 0 0, 0, 0 The code fails to compile at all on an a AT&T 3B20S SVR3.1 or a AT&T 3B4000 SVR3.1.5 and gives the following error output: cc e.c "e.c", line 17: too many struct initializers "e.c", line 17: too many initializers; missing } ? "e.c", line 17: operands of = have incompatible types "e.c", line 17: cannot recover from earlier errors: goodbye! Lint does not complain on any of these systems. The AT&T compiler and gcc will both compile with out errors if the five sets of braces surrounding each group of three items in the initialization are removed. A quick look through K&R1 did not find anything which would lead me to believe that the code as written is wrong. It seems to me that forcing the initialization to be 1 group of 15 items instead of 5 groups of 3 items does not make code maintenance easier but harder, especially if the structure definition and typedef are in a header file. Why is this no longer allowed? Any comments? Jim Apedaile Work: (415) 545-8300 WORK UUCP: {att,bellcore,sun,ames,pyramid}!pacbell!pttesac!jeapedai HOME UUCP: {att,bellcore,sun,ames,pyramid}!pacbell!pttesac!clab!jim ----------------------------- CUT HERE -------------------------- struct exp1 { int length; long grp1; long grp2; }; typedef struct { struct exp1 blk[5]; } RANGE; main() { static RANGE example = { { 40, 0xcf000, 0xff000 }, { 50, 0x1cf000, 0x1ff000 }, { 60, 0x2cf000, 0x2ff000 }, { 70, 0x3cf000, 0x3ff000 }, { 80, 0x4cf000, 0x4ff000 }, }; register RANGE *rptr; register int i; rptr = &example; for ( i = 0; i < 5; i++) (void)printf("%d, %lx, %lx\n", rptr->blk[i].length, rptr->blk[i].grp1, rptr->blk[i].grp2); return(0); } -- Jim Apedaile Work: (415) 545-8300 WORK UUCP: {att,bellcore,sun,ames,pyramid}!pacbell!pttesac!jeapedai HOME UUCP: {att,bellcore,sun,ames,pyramid}!pacbell!pttesac!clab!jim
walter@hpclwjm.HP.COM (Walter Murray) (01/24/90)
J. E. Apedaile writs: [sample program containing the following declarations] struct exp1 { int length; long grp1; long grp2; }; typedef struct { struct exp1 blk[5]; } RANGE; static RANGE example = { { 40, 0xcf000, 0xff000 }, { 50, 0x1cf000, 0x1ff000 }, { 60, 0x2cf000, 0x2ff000 }, { 70, 0x3cf000, 0x3ff000 }, { 80, 0x4cf000, 0x4ff000 }, }; > The AT&T compiler and gcc will both compile with out errors if the five > sets of braces surrounding each group of three items in the initialization > are removed. A quick look through K&R1 did not find anything which would > lead me to believe that the code as written is wrong. It seems to me that > forcing the initialization to be 1 group of 15 items instead of 5 groups of > 3 items does not make code maintenance easier but harder, especially if the > structure definition and typedef are in a header file. The problem here is not too many braces, but too few. You don't have "5 groups of 3 items", but rather "1 group of 5 groups of 3 items". The fully-bracketed initialization would look like this: static RANGE example = { { { 40, 0xcf000, 0xff000 }, { 50, 0x1cf000, 0x1ff000 }, { 60, 0x2cf000, 0x2ff000 }, { 70, 0x3cf000, 0x3ff000 }, { 80, 0x4cf000, 0x4ff000 }, } }; Note that the initializer begins with three left braces: one for example (a struct), one for example.blk (an array), and one for example.blk[0] (a struct). It is permitted to elide (omit) some of the braces, but doing so introduces an ambiguity, depending on whether the compiler parses the initializer top-down or bottom-up. Compilers that accept the example as originally given are probably using a bottom-up parse; K&R-I and the Standard both require a top-down parse. A Standard-conforming compiler is required to produce a diganostic for the program as originally written, because it looks like you are trying to initialize 5 members in example, but example has only 1 member. You are lucky the compiler complained. There are situations where the two methods of parsing initializers will yield different results and no diagnostic. The only safe approach is to write all braces, or to omit all but the outermost pair. Eliding some but not all is likely to result in portability problems. > Why is this no longer allowed? The Standard and its Rationale discuss this at some length. In the words of the Rationale, "The Standard has reaffirmed the (top-down) parse described in the Base Document [K&R-I]." In K&R-I, reread the last two paragraphs on page 198. > Any comments? I think Andrew Koenig ought to include an example of this in the next edition of _C Traps and Pitfalls_. Walter Murray -------------
maart@cs.vu.nl (Maarten Litmaath) (01/24/90)
In article <1515@pttesac.UUCP>, jeapedai@pttesac.UUCP (J. E. Apedaile) writes: \... \"e.c", line 17: too many struct initializers \... \struct exp1 { \ int length; \ long grp1; \ long grp2; \}; \ \typedef struct { \ struct exp1 blk[5]; \} RANGE; \ \ \main() \{ \ static RANGE example = { \ { 40, 0xcf000, 0xff000 }, \ { 50, 0x1cf000, 0x1ff000 }, \ { 60, 0x2cf000, 0x2ff000 }, \ { 70, 0x3cf000, 0x3ff000 }, \ { 80, 0x4cf000, 0x4ff000 }, \ }; Too many initializers indeed! I think you can figure out why the following is correct: static RANGE example = {{ /* note the `extra' brace! */ { 40, 0xcf000, 0xff000 }, { 50, 0x1cf000, 0x1ff000 }, { 60, 0x2cf000, 0x2ff000 }, { 70, 0x3cf000, 0x3ff000 }, { 80, 0x4cf000, 0x4ff000 }, }}; /* ...and its match */ -- What do the following have in common: access(2), SysV echo, O_NONDELAY? | Maarten Litmaath @ VU Amsterdam: maart@cs.vu.nl, uunet!mcsun!botter!maart
bumby@math.rutgers.edu (Richard Bumby) (02/01/90)
In <1515@pttesac>, jeapedai@pttesac.UUCP (J. E. Apedaile) asked about the behavior of various compilers in initializing a structure. I apologize for bothering the net with my response, but I don't trust our mailer to get to him as none of the links on the printed path appear to be known. The code in question is: struct exp1 { int length; long grp1; long grp2; }; typedef struct { struct exp1 blk[5]; } RANGE; main() { static RANGE example = {{ /* brace added */ { 40, 0xcf000, 0xff000 }, { 50, 0x1cf000, 0x1ff000 }, { 60, 0x2cf000, 0x2ff000 }, { 70, 0x3cf000, 0x3ff000 }, { 80, 0x4cf000, 0x4ff000 }, }}; /* brace added */ ..... } The extra braces noted enable the compiler on my laptop to compile the program successfully and give the expected result when executed. Further insertion of braces gives errors again. I have yet to try this on other compilers. Is it possible that the typedef introduces the need for an extra level of bracketing on some compilers? -- --R. T. Bumby ** Math ** Rutgers ** New Brunswick ** NJ08903 ** USA -- above postal address abbreviated by internet to bumby@math.rutgers.edu voice communication unreliable -- telephone ignored -- please use Email
chris@mimsy.umd.edu (Chris Torek) (02/02/90)
In article <Feb.1.09.43.53.1990.19730@math.rutgers.edu> bumby@math.rutgers.edu (Richard Bumby) writes: >Is it possible that the typedef introduces the need for an extra level >of bracketing on some compilers? No. Aggregate initialisers always take one level of braces for each aggregate. In this case---where we had struct exp1 { int length; long grp1; long grp2; }; typedef struct { struct exp1 blk[5]; } RANGE; an object of type `RANGE' needed a brace because it was a struct, plus a brace because the (single) element of that struct was an array; then, each element of the array needed a brace because it was a struct. Had the type definition been typedef struct { int somevalue; struct exp1 b1; struct exp1 b2[2]; int othervalue; } RANGE; this might have been more obvious: RANGE x = { /* somevalue */ 1, /* b1 */ { 1, 2, 3 }, /* b2 */ { /* b2[0] */ { 4, 5, 6 }, /* b2[1] */ { 7, 8, 9 }, /* b2 */ } /* othervalue */ 0 }; If you drop all but the b2/b2[0]/b2[1]/b2 lines, you get RANGE x = { { { 4, 5, 6 }, { 7, 8, 9 } } }; -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris