[comp.lang.c] Structure type comparison

bromley@think.COM (Mark Bromley) (03/05/88)

Historically, and in the latest Ansi C draft, each anonymous structure
declaration creates a new type.  Ie in the following x and y have different
types

	struct {int a;} x;
	struct {int a;} y;

This very much limits what can be done with objects of such types.  In the
above, you can assign to and use the value of x.a.  If more than one variable is
declared in such a declaration then any one of the variables can be assigned the
value of another (or the address if some of the variables are pointers).  And
that is all.  You can't return them from a function, or pass them as arguments
as their types are guaranteed not to match the function argument type or the
function result type.

I would suggest that in a world where structure values are first class objects
it is more useful to have type compatibility for anonymous structures be by
"contents" rather than by "name".  Ie two anonymous structure types are
compatible if they have the same number of members, the same member names,
compatible member types, and the members are in the same order.  There is a
considerable mental overhead to having to remember the exact type name rather
than just giving a description of the member types.

For example, I am implementing a (subset of) Common Lisp to C translator and am
using structure values to implement a form of multiple values.  I would like to
be able to produce code of the form:

struct {int _value_0; int _value_1;}
function (args)
{
  struct {int _value_0; int _value_1;} temp

  ...; temp._value_0 = exp; ...; temp._value_1 = exp1;

  return temp;
}

(Actually what I would like to produce is 

struct {int _value_0; int _value_1;}
function (args)
{
  ....; return (struct {int _value_0; int _value_1;}) {exp, exp1};
}
but that is another story (unless of course I am using GCC; so much for prior art).)

The code using this function would have the form

   struct {int _value_0; int _value_1;} temp = foo(args);

Currently I have to dream up a type name and use it consistently in both places.
Now it is certainly possible to get around this.  In a header file which is
included by both the file that defines the function and the file that uses the
function a definition of the following form is made

typedef struct {int _value_0; int _value_1;} MULTIPLE_VALUE_int_int;

Not only that, I must first check to make sure I haven't already defined this
type.  (For a number of reasons it is a bad idea to just produce a new name such
as MULTIPLE_VALUE_int_int_1).  As I said, not impossible, but a royal pain.

I have the feeling the ANSI comittee had something like this in mind when the
following sentences were written (pg 25, line 35 of the current draft):

	Moreover, two structure, union, or enumeration types declared in
	separate translation units are compatible if they have the same number
	of members, the same member names, and compatible member types.  For two
	structures, the members are in the same order.

I really don't understand these sentences.  When is it ever possible for a type
to be declared in one translation unit and compared to a type in another
translation unit without also being declared in the second translation unit?

Mark Bromley

henry@utzoo.uucp (Henry Spencer) (03/06/88)

> 	Moreover, two structure, union, or enumeration types declared in
> 	separate translation units are compatible if they have the same number
> 	of members, the same member names, and compatible member types.  For two
> 	structures, the members are in the same order.
> 
> I really don't understand these sentences.  When is it ever possible for a type
> to be declared in one translation unit and compared to a type in another
> translation unit without also being declared in the second translation unit?

It isn't.  The point is that even if the declaration of the type is picked
up from a header file, it looks to the compiler like two separate
declarations (one in file X and the other in file Y), which normally would
not be compatible even if they looked identical.  Passing structures (or
pointers to them, etc.) from one translation unit to another is proper
only if the types *are* compatible, so there has to be an escape clause
to make that possible.
-- 
Those who do not understand Unix are |  Henry Spencer @ U of Toronto Zoology
condemned to reinvent it, poorly.    | {allegra,ihnp4,decvax,utai}!utzoo!henry