[comp.lang.c] Alignment in C - it's simple

mo@uunet.UU.NET (Mike O'Dell) (05/05/88)

Alignment issues in C are actually quite simple,
and could actually be solved quite nicely in good ol'
Version 6 C, long before some of the more recent
"improvements."  This claim specifically applies to
C implementations of word-oriented machines as well
as byte-oriented ones.

There are actually two issues to consider: one is
resolution - how many bits it takes to address
an object, and alignment - what is the most
restrictive alignment required for addressing objects.

The C type with the greatest resolution is

	char *

pure and simple.  "char" is the smallest addressable
object in the language, and therefore takes the
most number of bits to address.  This is most obvious
in the word-addressed case where you must carry extra
bits beyond the basic address to get what you need.

On most real computers (but not IBM-PCs), double-precision
floats are usually the most highly aligned type,
making 
	
	double *
	
the most stringently-aligned type.

This means that the ANSI type

	void *

should represent like char * but align like double *

Usually, these are the maximal requirements for a value
returned from malloc(), and hence,

	void *malloc() 

is considered a completely correct statement of truth.

The problem which comes quickly to mind, however,
is that on Intel 8[012]86 machines, the screwiness of
the addressing architecture makes it mandatory in all
but one or two memory models for malloc()  to return
an object with 16-byte ("paragraph") alignment.
Since void * doesn't necessarily do that, it is
an incomplete semantic definition to simply declare

	void *malloc()

The claim made by that statement is true: the pointer returned
will have sufficient resolution to address (char *) and will
be at least as stringently aligned as (double *), but alas
that isn't the entire story.

In some sense, it boils down to what you want a declaration to
say.  Do you want a declaration to be a minimum requirement,
or a maximum requirement?  void *malloc() is certainly satisfied
by what the function returns, and is quite useful for most
cases, but when IMPLEMENTING malloc(), you better damn well
understand a great deal about the machine and how pointers 
really get used in the code generated by a particular compiler.


So, if we dismiss malloc() (and memory allocation in general)
as a terribly machine-dependent intrinsicly-unportable function,
which I think it must be, since it explicitly deals with
representations, then it comes down to whether you believe
a particular declaration is making a statement of some minimal
requirement met, or is making a promise about some other
issue such as alignment.  And if it weren't for the necessity
to make two different promises at once (I promise to use
enough bits to get at a char, but I won't ever return anything
which really really has any of those bits set!), (void *)
isn't really needed.  But it seems to be.

	Yours for clearer confusion,
	-Mike O'Dell