'struct' - declarations & parameters

Morris Keesan keesan at bbncca.ARPA
Wed Feb 22 08:54:31 AEST 1984


    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
					keesan @ BBN-UNIX.ARPA

More information about the Comp.lang.c mailing list