mcdaniel@uicsrd.csrd.uiuc.edu (Tim McDaniel) (07/29/89)
This is cross-posted to comp.lang.c (original article's newsgroup) and comp.std.c (I have standards questions). Followups have been redirected to comp.std.c. In article <13104@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve Summit) writes: >The production > > struct { struct-decl-list } id (arg-list) decl-list compound-statement > >yields a function that cannot be (correctly) called, since no >other object can be declared with a type-equivalent structure. I'm not so sure. Separate compilation is allowed in C, but struct tags (and their definitions) are not global in scope; for external linkage, only the types and order of the struct's members matter. I would think the following declarations are strictly conforming: in foo.c: extern struct { int f1; float f2; } func(); ... in bar.c: struct { int a6; float whacky; } func() ... However, K&R 2, 1st edition, p. 213 says A structure or union specifier with a list but no tag creates a unique type; it can referred to directly only in the declaration of which it is a part. >The production > > struct tag { struct-decl-list } id (arg-list) ... > >yields a function that can only be called by routines appearing >later in the same file. This statement is even more problematical. How does it differ from struct tag { struct-decl-list }; struct tag id (arg-list) ... ? If there is no difference, the "struct tag" declaration could just as easily be in an include file, and another file could include it and declare extern struct tag id (); Surely *this* behavior is blessed by the standard. -- "Let me control a planet's oxygen supply, and I don't care who makes the laws." - GREAT CTHUHLU'S STARRY WISDOM BAND (via Roger Leroux) __ \ Tim, the Bizarre and Oddly-Dressed Enchanter \ mcdaniel@uicsrd.csrd.uiuc.edu /\ mcdaniel%uicsrd@{uxc.cso.uiuc.edu,uiuc.csnet} _/ \_ {uunet,convex,pur-ee}!uiucuxc!uicsrd!mcdaniel
scs@adam.pika.mit.edu (Steve Summit) (08/01/89)
In article <1612@garcon.cso.uiuc.edu> mcdaniel@uicsrd.csrd.uiuc.edu (Tim McDaniel) writes: >This is cross-posted to comp.lang.c (original article's newsgroup) and >comp.std.c (I have standards questions). Followups have been >redirected to comp.std.c. Pooh. Now I have to be more careful than I can be, without a copy of the draft at hand... >In article <13104@bloom-beacon.MIT.EDU> scs@adam.pika.mit.edu (Steve >Summit) writes: >>The production >> struct { struct-decl-list } id (arg-list) decl-list compound-statement >>yields a function that cannot be (correctly) called, since no >>other object can be declared with a type-equivalent structure. > >I'm not so sure. Separate compilation is allowed in C, but struct >tags (and their definitions) are not global in scope; for external >linkage, only the types and order of the struct's members matter. It has been suggested that permission to base struct equivalence across files on types and order, rather than the stricter means required within one file, is an exception, reflecting the realities of conventional implementations of separate compilation. The way I think about it is that this is perfectly legal: s.h: struct s {int i;}; a.c: #include "s.h" b.c: #include "s.h" struct s s; extern struct s s; while this is suspect: a.c: struct s {int i;}; b.c: struct s {int i;}; struct s s; extern struct s s; Obviously, a conventional compiler cannot tell these two cases apart, which is why the exception allows the two struct s's in the second example to be considered equivalent. I would not mind it if a smart compiler (or, more preferably, lint) complained about the second form. I have no idea what the chapter and verse of the pANS says on this issue (that's why I'd have kept this in comp.lang.c...). I'm describing a conceptual ideal, based on the obvious stylistic requirement of describing the structure in exactly one place. If the pANS is less stringent (if its permission to base inter-file struct equivalence on type and order is not an exception, as I have suggested, but rather explicit and genuine) then I have no complaint with it, and you don't need to correct me here. (The standard tries to, and should, be pragmatic.) I hope we agree why the first sample code above is vastly preferable to the second. >>The production >> struct tag { struct-decl-list } id (arg-list) ... >>yields a function that can only be called by routines appearing >>later in the same file. > >This statement is even more problematical. How does it differ from > struct tag { struct-decl-list }; > struct tag id (arg-list) ... >? If there is no difference, the "struct tag" declaration could just >as easily be in an include file, and another file could include it... Of course. The difference between struct tag { struct-decl-list } id (arg-list) ... and struct tag { struct-decl-list }; ... struct tag id (arg-list) ... is precisely, and only, that the second form affords more possibilities for equivalent declarations of type "struct tag," especially if the tag is defined in a header file. That is exactly what I was trying to show. I listed three productions: 1. struct { struct-decl-list } id (arg-list) decl-list compound-statement 2. struct tag { struct-decl-list } id (arg-list) ... 3. struct tag id (arg-list) ... and suggested that the first one was, in practice, useless; the second one (theoretically) barely useful; and the third one the only one that would ever appear in real and/or well-written programs. Between the lines is a question, which I'll make explicit: if, in an attempt to catch the common mistake of misdeclaring main (or another function) by leaving out a semicolon after a preceding structure declaration, a compiler were to issue warnings for productions 1. and 2. above, would these warnings be elicited inappropriately for anyone's real programs? (No contrived examples or obfuscated C contest entries, of course.) Steve Summit scs@adam.pika.mit.edu