Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10 5/3/83; site bbncca.ARPA Path: utzoo!linus!bbncca!keesan From: keesan@bbncca.ARPA (Morris Keesan) Newsgroups: net.lang.c Subject: Re: 'struct' - declarations & parameters Message-ID: <599@bbncca.ARPA> Date: Tue, 21-Feb-84 17:54:31 EST Article-I.D.: bbncca.599 Posted: Tue Feb 21 17:54:31 1984 Date-Received: Wed, 22-Feb-84 04:02:44 EST References: <4033@edai.UUCP> Organization: Bolt, Beranek and Newman, Cambridge, Ma. Lines: 61 ---------------------------- It looks like the Orion compiler wins in all three cases. The last case is the simplest. The C Reference Manual is very clear that the declaration for each member of a structure requires a ';' at the end of it, so in this case the Orion compiler is clearly right, and the VAX compiler you're using is in violation of the language definition. The other two cases are not quite so straightforward. Both compilers are behaving in completely legal fashion, since the language definition says nothing about how argument passing is to be implemented (except that the semantics are "call by value"). The source code is at fault here, since it was written to expect the implementation of the calling sequence which is provided by the VAX compiler (and similar compilers). Passing a structure as if it were three integers runs you right into the "varargs" problem. From page 71 of K&R: By the way, there is no entirely satisfactory way to write a portable function that accepts a variable number of arguments, because there is no way for the called function to determine how many arguments were passed to it in a given call. . . . It is generally safe to deal with a variable number of arguments if the called function doesn't use an argument which was not actually supplied, and if the types are consistent. printf . . . fails badly if the caller does not supply enough arguments or if the types are not what the first argument says. This suggests that > struct {int a, b, c;} foo = {1, 2, 3}; > main () { printf("%d %d %d\n", foo); } is bogus and should never have been coded that way. Your second example, passing pointers as if they were unions, is clearly illegal because of type mismatch between the formal and actual parameters. Lint should have complained about this. Assuming you know enough about the target machine and the compiler implementation to know that (char *) and (double *) are the same size, and that a union of the two is also that size, the slightly more portable way of coding your second example would be union foo {char *c; double *d;}; void bother(x,i) union foo x; int i; { . . . } void main() { bother((union foo)pc, 1); bother((union foo)pd, 0); } but this is still non-portable and not guaranteed to work (if, for example, char pointers are a different size from other pointers). Incidentally, both of these rather bogus code samples work okay on a C70, although the second one won't work with the "void" declarations until my newer version of the compiler is released. -- Morris M. Keesan {decvax,linus,wjh12,ima}!bbncca!keesan keesan @ BBN-UNIX.ARPA