[comp.lang.c] `Display *display;' and such

weeks@hpdtczb.HP.COM (Greg Weeks) (05/30/91)

To illustrate a point about C programming style, here is a bit of the
documentation for a typical XWindows function:

	XRaiseWindow (display, window)
		Display *display;
		Window window;

There is an oddity here.  A `display' is a pointer to a `Display', while a
`window' is just a `Window'.  Most of you reading this understand why this
is so.  `Window' is some integer type, but `Display' is a structure type;
and we are all familiar with the need to use pointers to structures.

Still, the code looks odd.  Is this oddness necessary?  Could the style be
improved?  At what cost?

I believe that the style could be significantly improved with only minor
disadvantages.  The rest of this note explains how and why.


TWO WAYS THAT DATA TYPES REPRESENT REAL-LIFE OBJECTS

Some real-life objects are visualized in the computer as patterns of bits.
For example, the integer 3 is visualized as 0...011.  Other real-life
objects are visualized as blocks of memory that hold varying patterns of
bits.  For example, my bank account, crudely modelled as holding my current
balance measured in pennies, may be visualized as a block of memory holding
an `int' value.  As my balance changes, the value held in the block of
memory changes, but the block of memory itself stays put.

There is no agreed upon term for a block of memory that holds data.  K&R
use the term "object".  Others use the term "variable".  In this note,
"variable" will be used to denote a block of memory that holds data.  So,
while the amount of money in my bank account may be represented by an `int'
value, the bank account itself is represented by an `int' variable.

Similarly, while the current state of a display is represented in XWindows
by a structure value, the display itself is represented by a structure
variable.

What then is the type whose _values_ represent displays?  We're looking for
a type whose values represent variables.  The obvious answer is pointers.
This representation is not perfect -- after all, pointers and variables are
different -- but it is the best we can do.  So, the type whose values best
represent displays is a pointer type.


STRUCTURE VS POINTER

So, there are two sides to the issue "Is an XWindows display a structure or
a pointer?"  Both sides are correct, but they tug in opposite directions.

Side 1: The type whose variables best represent real-life displays is a
	structure type.

Side 2: The type whose values best represent real-life displays is a
	pointer type.

A symptom of this split is our problem with the declaration:

		Display *display;

The type name and the variable name are on different sides of the issue.
The name `Display' for a structure type is on Side 1.  The name `display'
for a pointer variable is on Side 2.  A pure Side 1 declaration would
rename the variable, eg:

		Display *displayPtr;

A pure Side 2 declaration would have the name `Display' refer to a pointer
type:

		Display display;      /* HERE, `Display' IS A POINTER TYPE */


TAKING SIDES

Now for value judgments.

The both-sides approach of `Display *display;' is gross.  Either pure Side
1 or pure Side 2 would be preferable.

I'm on Side 2, for various reasons.  

When discussing which data types represent real-life objects, it is much
tidier to have only one way to represent things -- with values.  The "with
variables" way makes no sense in Lisp, CLU, or Smalltalk, and I hope that
it isn't much used in Pascal.

Side 2 code looks nicer than Side 1 code.  Side 2 code better reflects the
relationships found among real-life objects.  And it has fewer *'s.

The pointer type is used more than the structure type.  The structure type
is useful only for allocating the variables that are pointed to.

Side 1 code precludes data abstraction.  In contrast, Side 2 code would
allow displays to be implemented as indexes into an array of preallocated
structures (similar to XWindows window-ids or to Unix file-descriptors).


A POINT FOR SIDE 1

As noted above, the structure type is useful only for allocating the
variables that are pointed to.  If the allocation is in the heap, it is
natural to write a function that allocates the variable and returns the
pointer to it.  Users of the function need never be exposed to the
structure type.

In Lisp, Pascal, CLU, and Smalltalk, allocation of variables that are
pointed to _must_ occur in the heap.  So the structure type may be hidden
at no cost.  But in C, it is possible, for example, to allocate a `Display'
structure variable in the stack or in the data area; the address of the
variable may then be passed to functions that expect a pointer.  This
practice is to some degree more convenient and more efficient than heap
allocation.  [It also violates data abstraction.]

Allocating a stack (or data area) variable and passing its address to
functions that expect a pointer is a practice that makes perfect sense
viewed from Side 1.  But it is a bit kludgy viewed from Side 2.  Oh well.

weeks@hpdtczb.HP.COM (Greg Weeks) (05/30/91)

As the writer of the basenote, I think I'd better say what it was for.

Mostly, I'd like to hear from people who agree.  No one is likely to be
swayed by the arguments themselves -- how often does that happen in notes
groups?  But I hope people who agree already will be able recognize their
opinions in the basenote which, in summary, says this:

    A mutable real-life object has a fixed identity in addition to a
    variable state.  The state may be represented with a structure, but the
    object itself should be represented with a pointer.

To those who agree: lets commiserate.