From: torek@horse.ee.lbl.gov (Chris Torek)
Newsgroups: comp.lang.c
Subject: prototype and old-style types (was Really weird C warning)
Date: 26 Jul 1992 00:06:37 GMT
Organization: Lawrence Berkeley Laboratory, Berkeley
Reply-To: torek@horse.ee.lbl.gov (Chris Torek)
NNTP-Posting-Host: 128.3.112.15

In an article whose referent was deleted by deficient news software,
someone whose initials are presumably DJP (article
<4009.107.uupcb@cutting.hou.tx.us> used `DJP>' as a quote indicator)
wrote:

>For the sake of argument, suppose sizeof(int) == 2, sizeof(long) == 4,
>sizeof(char *) == 4, and I have a compiler that aggresively conserves
>stack space. ... If [a function F taking, in order: long, char, char *]
>is declared as a K&R function, the size of the argument vector thus
>passed would then be 4 + 2 + 4 == 10.  (Remember, longs remain long, and
>chars are promoted to int.)  Alternately, if F is declared with a
>prototype, the compiler is completely within its rights to allocate
>the argument vector as 2 + 1 + 4 == 7 ....  The long is converted to int.
>The char remains a char.

(Some context appears to be missing, as the long => int conversion should
occur only if the first formal parameter to F has type `int' and there is
a prototype in scope.  The material I inserted (in [] above) presumably
differs from DJP's original, or else this is a mistake and the size should
be 4+1+4 or 9.)

In article <4009.107.uupcb@cutting.hou.tx.us>
matt.johnson@cutting.hou.tx.us (Matt Johnson) writes:
>Huh?  This I gotta see to believe.  Don't think there is a Push AL
>instruction for the 80x86 family...

Since this is comp.lang.c, not an 80x86-specific newsgroup, bringing up
particular instructions is generally unwise.  Nonetheless, one can
easily imagine a compiler that uses `movb' to put char arguments on the
IBM PC stack, having allocated the proper number of bytes using simple
subtraction.

In any case, DJP's point stands as the primary motivation behind the
rules in ANSI C for mixing prototypes and K&R-style definitions.  Or
rather, it does once it is augmented with a bit of history.

Classic C promoted arguments always.  If you attempted to pass a char,
short, or float value to a function, that function actually *got* an
int or a double.  A number of vendors objected on the grounds that
avoiding promotion (and subsequent demotion) was unnecessarily
inefficient.

The ANSI C committee decided, then, to allow compilers to omit any
unnecessary promotion-and-demotion code IF AND ONLY IF *both* the
caller and the callee used New C conventions.  The caller must have a
prototype in scope; this gives the compiler license to send arguments
without first promoting char, short, and float.  Similarly, the
callee---the destination function---must use the new prototype-like
definition syntax.

As an aid toward catching mistakes, the ANSI C committee decided that,
if the compiler sees a function definition while a prototype for that
function is also in scope, it must check that each formal parameter has
an `unpromotable' type.  Thus, given

	void f(char);		/* this is a new-style declaration */

	void f(c)		/* this is an old-style definition */
		char c;
	{
		/* your code goes here */
	}

an ANSI C compiler must issue at least one diagnostic, because the
definition claims that f() should receive one `int'---the type of
`char' after promotion---but the prototype claims that f() should
receive one `char'.

It has been observed on this group before that MS C 6.0 gets this much
right, but gets something else wrong:  It comes with a program (the C
compiler, actually) that purports to generate correct prototypes from
correct old-style code.  This program actually generates incorrect,
incompatible prototypes, and the C compiler correctly complains about
clashes between these prototypes and the old-style definitions.

It seems a bit peculiar that a single program, albeit a complex one
with multiple modes of operation, should be inconsistent in this way.
It gets the diagnostic right but emits incorrect prototypes.  The most
likely explanation, Microsoft being Microsoft, is that two different
programmers handled the different modes, and only one read the ANSI C
standard.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov