[comp.lang.c] Undeclared function arguments

Rick 'Transputer' Stein@dhw68k.cts.com (Rick 'Transputer' Stein) (10/14/88)

I wonder if any of you gurus can comment on the following fragment of
code output from lex:

The function yyback has two arguments, but only one is typed in argument
the list.  Why does my C compiler or lint, for that matter, not complain?

yyback(p,m)
int *p;
{
	if (p==0)return(0);
	while(*p)
	{
	  if ( *p++ == 0 )return(1);
	}
	return(0);
}

I've compiled this fragment along with the body of lex.yy.c on many
machines and compilers (SGI/4D, HP9000, SUN/4, Inmos transputers with
3L,MSC 4.0, etc) and no errors have been generated.  Are undeclared
function arguments auto casted to pointers?

Thanks in advance.

+--------------------------+---------------------------------------+
| Rick 'Transputer' Stein  | uucp: ...{felix, zardoz}!dhw68k!stein |
| "Goddam digital confuser | MaBellnet: 714-786-7794 (H)           |
| technology..."           |            714-540-8900 (W)           |
| Disclaimer: These opinions are mine, not my employer's.          |
+--------------------------+-------------------------------------- +

rkl1@hound.UUCP (K.LAUX) (10/17/88)

	YYBACK (i, m)
	int i;
	{
	...
	}

	The reason that 'm' was not declared was that the body of the
function did not reference the variable at all *AND* it was the last
parameter in the formal argument list.  Since arguments are pushed on
the stack from *right* to *left*, there was no need to know its size.

	It would be a different case if:

	YYBACK (i, m, n)
	
	and only i and n were referenced because now the compiler would
*have* to know the size of m in order to correctly reference n on the stack.

--rkl

	

psrc@poseidon.ATT.COM (Paul S. R. Chisholm) (10/17/88)

<"He seemed like such a nice man . . . and then he turned out to be a writer!">

In article <13168@dhw68k.cts.com>, Rick 'Transputer' Stein@dhw68k.cts.com
(Rick 'Transputer' Stein) asks why the following compiles cleanly:

yyback(p,m)
int *p;
{
	if (p==0)return(0);
	while(*p)
	{
	  if ( *p++ == 0 )return(1);
	}
	return(0);
}

> I've compiled this fragment along with the body of lex.yy.c on many
> machines and compilers (SGI/4D, HP9000, SUN/4, Inmos transputers with
> 3L,MSC 4.0, etc) and no errors have been generated.  Are undeclared
> function arguments auto casted to pointers?
>Rick 'Transputer' Stein, {felix, zardoz}!dhw68k!stein

According to K&R 1st ed. (p. 205), "Any [parameter-list] identifiers
whose type is not given are taken to be int."  p is declared and used
as a pointer.  m is implicitly declared an int, and not used at all!
(But lint should have complained about m as an unused argument.)

Paul S. R. Chisholm, psrc@poseidon.att.com (formerly psc@lznv.att.com)
AT&T Bell Laboratories, att!poseidon!psrc, AT&T Mail !psrchisholm
I'm not speaking for the company, I'm just speaking my mind.

jfh@rpp386.Dallas.TX.US (The Beach Bum) (10/19/88)

In article <2686@hound.UUCP> rkl1@hound.UUCP (K.LAUX) writes:
>	The reason that 'm' was not declared was that the body of the
>function did not reference the variable at all *AND* it was the last
>parameter in the formal argument list.  Since arguments are pushed on
>the stack from *right* to *left*, there was no need to know its size.

This is not portable, relevant, or correct.

The formal argument `m' has a default type of `m', hence the type and
size are known, as a matter of fact.  Regardless of `m' being referenced,
the type will always default to `int'.

The order of arguments on the stack, or even the existance of a stack,
is not an issue which is addressed by the language specification.  There
exists hardware in which a function with two arguments will pass the
actual parameters are passed in registers or pre-allocated regions of
memory.

>	It would be a different case if:
>
>	YYBACK (i, m, n)
>	
>	and only i and n were referenced because now the compiler would
>*have* to know the size of m in order to correctly reference n on the stack.

This would be correct if the size of `m' were not set by default to be
sizeof (int).  If the call were

YYBACK (i, m, n)
int	i;
struct	foo	m;
int	n;

and the size of `m' weren't known, THEN it MIGHT be an issue.  However,
only structure pointers do not require the size of the underlying structure
to be known.  Since `m' in this case is not a pointer, this exception does
not apply and the above example is illegal.

C provides that undeclared formal parameters default to type `int'.  This
may not be a wonderful idea, but it does cover this situation.
-- 
John F. Haugh II                        +----Make believe quote of the week----
VoiceNet: (214) 250-3311   Data: -6272  | Nancy Reagan on Richard Stallman:
InterNet: jfh@rpp386.Dallas.TX.US       |          "Just say `Gno'"
UucpNet : <backbone>!killer!rpp386!jfh  +--------------------------------------

guy@auspex.UUCP (Guy Harris) (10/19/88)

>Since arguments are pushed on the stack from *right* to *left*,

"Are pushed" in some implementations, anyway; there is no requirement in
any language spec that says it has to be done that way.

rkl1@hound.UUCP (K.LAUX) (10/20/88)

 In article <8058@rpp386.Dallas.TX.US>, jfh@rpp386.Dallas.TX.US (The Beach Bum) writes:
 > In article <2686@hound.UUCP> rkl1@hound.UUCP (K.LAUX) writes:
 > >	The reason that 'm' was not declared was that the body of the
 > >function did not reference the variable at all *AND* it was the last
 > >parameter in the formal argument list.  Since arguments are pushed on
 > >the stack from *right* to *left*, there was no need to know its size.
 > 
 > This is not portable, relevant, or correct.
 > 
 > The formal argument `m' has a default type of `m', hence the type and
 > size are known, as a matter of fact.  Regardless of `m' being referenced,
 > the type will always default to `int'.
 > 
 > The order of arguments on the stack, or even the existance of a stack,
 > is not an issue which is addressed by the language specification.  There
 > exists hardware in which a function with two arguments will pass the
 > actual parameters are passed in registers or pre-allocated regions of
 > memory.
 > 
 > >	It would be a different case if:
 > >
 > >	YYBACK (i, m, n)
 > >	
 > >	and only i and n were referenced because now the compiler would
 > >*have* to know the size of m in order to correctly reference n on the stack.
 > 
 > This would be correct if the size of `m' were not set by default to be
 > sizeof (int).  If the call were
 > 
 > YYBACK (i, m, n)
 > int	i;
 > struct	foo	m;
 > int	n;
 > 
 > and the size of `m' weren't known, THEN it MIGHT be an issue.  However,
 > only structure pointers do not require the size of the underlying structure
 > to be known.  Since `m' in this case is not a pointer, this exception does
 > not apply and the above example is illegal.
 
 	You're absolutely right about non-declared variables defaulting to
 'int'.  It's also true that stacks are not part of the language specification.
 However, its not uncommon for compilers to use a stack and to push arguments
 from right to left (MSC, AT&T, DEC...)
 
 	I find that I often need to check the assembly language generated to
 see just what's going on (usually I'm reworking already written code) and, upon
 reflection of writing the above, I can see I was definitely influenced by
 my experiences (...why is it *I* always have to find those subtle compiler bugs
 the hard way...oh, well).
 
 --rkl