Prototypes, was Why NULL is 0

Pablo Halpern pablo at polygen.uucp
Tue Mar 22 12:23:38 AEST 1988


>From article <25699 at cca.CCA.COM>, by g-rh at cca.CCA.COM (Richard Harter):
> 	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.

Not true.  Although prototypes do duplicate some of the purpose of lint,
they do more than that.  One example is telling the compiler what
representation to cast NULL into (see other postings under this subject
header).  Other uses of prototypes: tell the compiler it doesn't need
to coerce a float into a double or an int into a long. (ANSI implies
that if a function call is made in the presence of a prototype, the
programmer is responsible for making sure the same prototype is present
for that function's definition, thus assuring that caller and called
agree on how to pass the parameters.  Unlike the Ada spec, X3J11 doesn't
attempt to address the environment that keeps these things in sync.)

Also, the compiler can figure out when to cast a short to an int or
long when passing an integral type.  This can be important when calling
library routines.  For example, X3J11 defines the argument of malloc()
to be of type size_t, which is an implementation defined integral type.
K&R defined the argument of malloc() to be an int, causing a problem
for users of compilers where the address range doesn't fit in an int
(e.g. 8086 large memory model: address range = 1M, int range = 64K).
Using strict K&R definitions, code that allocated large chunks of
memory was not portable to these machines because the argument of
malloc() wouldn't fit in an int.  Redefining malloc() to take a long
doesn't work either because every use of an integer literal as an
argument to malloc() would have the wrong type (int instead of long)
and would be passed incorrectly by the compiler.  Lint would catch
these errors but that doesn't address the problem that the same
code won't work on two different machines.  Prototypes solve the
problem by allowing the compiler writer to define size_t as long
without forcing the compiler user (programmer) to change his/her
code.  The compiler now knows (assuming a prototype for malloc()
is included in the right places) to cast integer arguments into
longs (size_t) before passing them to malloc().

So you see, prototypes can significantly improve the portability
of C programs.  "Prototypes: they're much more than error detectors."

Pablo Halpern		|	mit-eddie \
Polygen Corp.		|	princeton  \ !polygen!pablo  (UUCP)
200 Fifth Ave.		|	bu-cs      /
Waltham, MA 02254	|	stellar   /



More information about the Comp.lang.c mailing list