[comp.lang.c] nargs

karl@haddock.UUCP (01/31/87)

While discussing ways to declare variadic functions (primarily to lint), I
mentioned the possibility of a lint-pragma /* SENTINEL (char *)0 */ for the
execl family, and some other notation for functions that receive an arg count
as one of the args.  In a footnote, I observed that neither would be needed if
C were to support nargs().

Somebody posted a followup with some objections.  The article expired before I
had a chance at rebuttal, so the following quotes are approximate.

>The number of args isn't useful without also knowing the types.

Since we were talking about monomorphic functions (execl, not printf), the
types are known.  The feature may also be useful for a robustness-check in
printf-like functions, but that's a separate issue.  I'll discuss both here.

>nargs() as usually implemented returns the number of words, not the actual
>number of args.

One can convert either to the other via sizeof().  If this feature is to be
used by polymorphic functions, it's probably best to return the total size of
(the variadic portion of) the arg list in bytes, to allow constructs such as
"for (n = nargs(); n != 0; n -= argsize)".

>The pdp11 implementation had to dig this information out of I-space.  In
>general, it's inefficient.

I see three objections here, which I'll rephrase.

>Some machines (pdp11 sep-I/D) are incapable of implementing the classical
>nargs().

If it were part of the standard language, conforming compilers would *have* to
allow some hook to retrieve the information.  On the vax, it's already there
as a zeroth arg; nargs() could be a builtin that just picks up the information
from the stack.  On the pdp11, it would be implemented by passing a "hidden"
arg, probably in a scratch register.

>The overhead is unacceptable.

The overhead of "movei r0,12" is pretty small compared to that of the typical
procedure-invocation protocol.  If a scratch register is used, the callee can
ignore the information at no additional cost.

>Most functions don't need the information.

Since ANSI C requires you to explicitly declare variadic functions, the nargs
information need not be passed to ordinary functions.  The execl family could
make good use of the information (possibly making the call cheaper; certainly
making it more robust).  The members of the printf family have to compute the
arg count (and types) from the format string anyway, so in this case nargs()
is redundant except as an error check.  But if you're worried about functions
doing more work than they need to, you don't use printf() anyway.  :-)

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint