Protoize/Unprotoize (was: ANSI C to K&R syntax converter)

Stephen Clamage steve at taumet.com
Wed Jun 6 01:56:01 AEST 1990


In article <1645 at mountn.dec.com> minow at thundr.enet.dec.com (Martin Minow) writes:
>I've had good results by writing prototypes using the following process:
> [ details deleted ]
>	/*
>	 * All functions are specified here:
>	 */
>	int		sample _((int, char *, struct foo));
>The actual definition of a function uses the old -- but still valid -- syntax:
>	int sample(i, cp, foostruct)
>	int		i;
>	char		*cp;
>	struct foo	foostruct;

This will not work properly if any of the parameters are of type char,
short, or float.  If you are lucky, the ANSI compiler will complain about
mismatched prototype and defintion if the prototypes are in scope when the
definition occurs.

Consider the prototype
	int foo(float f);
and the definition
	int foo(f)
	float f;
	{ ... }
and the call to foo
	int x = foo(1.0);

With an ANSI compiler, the compiler will see the prototype and know that
foo expects to see a float parameter.  It will pass a float version of
1.0 to foo().

At the definition point, assume the compiler doesn't see the prototype.
It will see an old-style definition, and know that any caller will have
actually passed a double, not a float, by the rules of default promotion.
So it will expect to be passed a double, which is different in size and
in format from floats on most machines.

So the caller passes a different type than the called function expects.
Sad to say, your solution is not portable.

You can make it portable by conditionalizing the function definition:
#if __STDC__
	int sample(int i, char *cp, struct foo foostruct)
#else
	int sample(i, cp, foostruct)
	int		i;
	char		*cp;
	struct foo	foostruct;
#endif
{ ...
}

Unfortunately, this is very ugly and error-prone.
-- 

Steve Clamage, TauMetric Corp, steve at taumet.com



More information about the Comp.lang.c mailing list