[net.lang.c] struct element orderin vs. alignment.

kpmartin@watmath.UUCP (Kevin Martin) (01/05/85)

There seem to be people who are saying, effectively, if the language user
doesn't care about struct element alignment, he/she also deson't care
about element ordering (you care about alignment for device registers, which
are machine dependant already, right?). The problem is, that this isn't true.
 
There are many programs which believe that two structures with the same
initial set of elements have the same ordering for those elements. This
prevents the compiler from (by default) re-ordering the elements.
 
In other words, it is possible for the programmer to care about the order, but
not the alignment, of struct fields.
                               Kevin Martin, UofW Software Development Group

Mark.Tucker@CMU-CS-GANDALF.ARPA (01/08/85)

>> There are many programs which believe that two structures with the same
>> initial set of elements have the same ordering for those elements.
>
>Fie!  For shame!  It was for this reason (among others) that unions
>and separate name spaces among structs were born.  Having two structs
>with the same initial set of elements -- and trusting them to stay
>that way, even through your novice programmer's "fixes" and the new
>A. E. Neumann C Compiler XXX -- isn't all that reliable.
>
>Joe Yao		(UUCP!seismo!hadron!jsdy / hadron!jsdy@seismo.ARPA)

Sigh,
	until you give me a subclass mechanism that ensures that the
representation of two data types share a common prefix, I'll rely on this
compiler hack.  Yes, you can declare a new type to represent the common
prefix part, but a proliferation of new little types can also confuse the
innocent.

	typedef struct{
		foo a,b;
		} prefix;

	typedef struct{
               prefix p;
	       < t1 specific>
	       bar c;
	       } t1;
	
	typedef struct{
	       prefix p;
	       < t2 specific >
	       baz d;
	       } t2;

   .... 	aT1.p.a   .... aT1.c

You could fix the lack of uniformity in using shared-vs-unique fields by
having more control over the naming environment.  For instance, you could
define
	typedef OPEN struct{...} prefix;
where the "OPEN" modifier allows unqualified access to fields defined in
the the type "prefix."
Thus, when fields of type prefix are defined, the namespaces of "prefix"
and those of the record being defined arenot disjoint.

	Then, once better control over names are in place, you can introduce
PUBLIC, PRIVATE, OPAQUE and get clusters....

-- Mark Tucker

ekb@link.UUCP (Eric K. Bustad) (01/12/85)

> >> There are many programs which believe that two structures with the same
> >> initial set of elements have the same ordering for those elements.
> >
> >Fie!  For shame!  It was for this reason (among others) that unions
> >and separate name spaces among structs were born.  Having two structs
> >with the same initial set of elements -- and trusting them to stay
> >that way, even through your novice programmer's "fixes" and the new
> >A. E. Neumann C Compiler XXX -- isn't all that reliable.
> >
> >Joe Yao		(UUCP!seismo!hadron!jsdy / hadron!jsdy@seismo.ARPA)
>
> Sigh,
> 	until you give me a subclass mechanism that ensures that the
> representation of two data types share a common prefix, I'll rely on this
> compiler hack.  Yes, you can declare a new type to represent the common
> prefix part, but a proliferation of new little types can also confuse the
> innocent.
>		. . .
>
> -- Mark Tucker

I suspect that Joe had something like this in mind:

	#define T1 0
	#define T2 1

	typedef struct {
		int subclass;	/* either T1 or T2 */
		foo a,b;
		union {
			struct {
				foo c
				bar d;
			} t1;
			struct {
				foz c;
				baz e;
			} t2;
		} noncom;
	} bigclass;
	
	bigclass aT1 = { T1, <initial values for other common fields> };

	....  aT1.a
	if (aT1.subclass == T1) {
		.... aT1.noncom.t1.c ....
	}

The referencing of non-common fields does get rather ugly,
but this will certainly ensure that T1 and T2 structures
have the same prefix.

= Eric Bustad (AT&T Bell Laboratories, Holmdel NJ)
  +1(201)949-6257
  ihnp4!eric.bustad or link!ekb

ka@hou3c.UUCP (Kenneth Almquist) (01/12/85)

There are two problems with using unions to deal with elements shared
between more than one structure.  As an example, consider the System V
message system call.  Each message begins with a long integer specifying
the message type; the contents of the rest of the message are left to
the applications programmer.  Thus if we used a union to declare these
messages, we would have:
	struct message {
		long m_type;
		union {
			struct msg1 msg1;
			struct msg2 msg2;
			...
			struct msgn msgn;
		} m_union;
	};

Two considerations make this impractical.  One is administrative; every
time a new program was written using the message system call, the union
would grow and the kernel would have to be recompiled (especially tough
for folks with binary only licenses).  The second problem is technical;
there is no portable way to allocate only the amount of memory needed
for a given message.  Allocating "sizeof(struct message)" bytes for each
message may be intolerably inefficient.

It is in part for these reasons that C compilers are not allowed to re-
order structure members.  Currently messages can be handled conveniently
by declaring structures that will begin with a long since C will leave the
type at the beginning of the structure where the programmer put it.

> > >Having two structs
> > >with the same initial set of elements -- and trusting them to stay
> > >that way, even through your novice programmer's "fixes" and the new
> > >A. E. Neumann C Compiler XXX -- isn't all that reliable.

A novice programmer or a nonworking compiler can break any code.  I am
not convinced that sharing structure elements is an exceptionally
confusing practice (at least not by C standards :-)).
					Kenneth Almquist