Prototypes, was Why NULL is 0

Richard Harter g-rh at cca.CCA.COM
Sat Mar 19 03:47:28 AEST 1988


In article <784 at cresswell.quintus.UUCP> ok at quintus.UUCP (Richard A. O'Keefe) writes:
]In article <25652 at cca.CCA.COM>, g-rh at cca.CCA.COM (Richard Harter) writes:
]> I don't know if this is what ANSI C expects, but it's not too hot if
]> it is, because we now have two descriptions of the calling sequence.
]> The right thing is simply
]> 
]> #include "prototypes.h"
]> ....
]> type_of_foo foo(a,b) {....}
]> 
]> In fact, even type_of_foo should be omitted, since that is really part
]> of the description.
]> 
]It depends what you mean by "the right thing".
]If you mean "whatever means I have less to write", fine.
]If you mean "whatever makes C more like Pascal", fine.
]If you mean "whatever will make the code easier to maintain",
]you're dead wrong.

	I mean, of course, none of these things.  I was referring to
the ancient and venerable principle of programming that an entity should
only be defined in one place.  The reason for this is (my apologies for
rehashing something you know very well) that if an entity is defined
in more than one place and it is has to be changed than all instances
have to be changed uniformly.  Miss one, for whatever reason, and the
code becomes inconsistent.

	The reason for saying that the above  is "the right thing"
to do is that the prototype (whether in a header file or in the code)
need not match the declarations in called routine.  The reason for
this is simple -- you have specified the number and types of arguments
in the calling sequence (a single entity) in several places.

	To be sure, if you use Lint or an equivalent tool, it will
catch this.  However Lint will catch this sort of thing even if you
don't have prototypes.

]When as Joe Maintainer I come along and try to figure out what your function
]foo() does, I want to be able to see what the arguments and result are,
]which means that I want them *right* *there* with the rest of foo(), where
]I can see them.  In fact, I want all the immediately useful information to
]be there where I don't have to hunt all over file space to find it.

	This is the other side of the coin -- there is another venerable
principle that says that all relevent information should be immediately
accessible.  When you put things in a header file, they are no longer
visible in the code.  And this does slow down maintenance -- time spent
looking things up (or worse yet, not looking things up and making incorrect
assumptions) costs.

	There are various partial solutions.  For example, you can replicate
definitions and have the compiler check things.  I.e. "prototypes.h" would
contain a standard description, the calling routines contain prototypes
(to provide information to the programmer) and the called routines contain
declarations (again for information purposes).  The compiler would then
check consistency of specification(given in the header file) against
the information given in the code.  This leaves the maintenance problem
(multiple specifications to alter) but at least ensure consistency.

	One can thing of other solutions.  What they all have in common,
as far as I can see, is that they stray a good deal of distance from the
the way things are done now.

	As it stands, the real value of a prototype is informative --
the calling routine can contain a description of a calling sequence.
Its value for protecting against erroneous usage of routines is nominal;
lint is really much more useful.  A prototype declaration does not protect
you against an incorrect prototype declaration because it does not 'look'
at the real master (the actual declaration in the code in the called routine)
whereas lint does.
-- 

In the fields of Hell where the grass grows high
Are the graves of dreams allowed to die.
	Richard Harter, SMDS  Inc.



More information about the Comp.lang.c mailing list