Path: utzoo!mnetor!uunet!husc6!tut.cis.ohio-state.edu!bloom-beacon!bu-cs!polygen!pablo From: pablo@polygen.uucp (Pablo Halpern) Newsgroups: comp.lang.c Subject: Re: Prototypes, was Why NULL is 0 Message-ID: <134@polygen.UUCP> Date: 22 Mar 88 02:23:38 GMT References: <25699@cca.CCA.COM> Organization: Polygen Corporation, Waltham, MA Lines: 48 From article <25699@cca.CCA.COM>, by g-rh@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 /