[comp.lang.c] Variable number of arguments to a function

thssvhj@iitmax.IIT.EDU (vijay hemraj jadhwani) (05/06/90)

Here is a question for c folks. 
I have a function myprint() as follows -

myprint(stream, fmt, a1, a2, a3, a4, a5)  /* Function definition */
FILE *stream;
char *fmt;
{
	... some initialization and assignment ...
	sprintf(stream, fmt, a1, a2, a3, a4, a5);
			.
			.
			.
}

Below are the three different cases of function references (or usage).
Case 1. ACTUAL NO. OF ARGUMENTS < NO. OF ARGUMENTS IN THE FUNC. DEFINITION

	int test_no = 1;
	myprint(stderr, "This is just test number %d", test_no);



Case 2.  ACTUAL NO. OF ARGUMENTS > NO. OF ARGUMENTS IN THE FUNC. DEFINITION

	int a, b, c, d, e, f;
	myprint(stderr, "The values are %d %d %d %d %d %d", a, b, c, d, e, f);




Case 3: ARGUMENT TYPE IS DIFFERENT THAN THE EXPECTED ARGUMENT TYPE

	int a;
	float b; /* This argument type is different; default type is int */
	int c, d, e;
	myprint(stderr, "The values are %d %f %d %d %d", a, b, c, d, e);


Questions -
1. Which of the above 3 cases are correct and which are not? Why ?

2. If I want to remove any "lint" warnings, for argument number mismatch,
   what should I do ? i.e. I need a scheme to be able to pass variable
  number of arguments to myprint(). Also it would be nice , if I could 
  also have an ability to  pass any "type" of arguments to myprint().

Thanks in advance for any help.
Vijay.

chris@mimsy.umd.edu (Chris Torek) (05/06/90)

In article <3697@iitmax.IIT.EDU> thssvhj@iitmax.IIT.EDU
(vijay hemraj jadhwani) writes:
[code examples deleted]
>Case 1. ACTUAL NO. OF ARGUMENTS < NO. OF ARGUMENTS IN THE FUNC. DEFINITION
>Case 2.  ACTUAL NO. OF ARGUMENTS > NO. OF ARGUMENTS IN THE FUNC. DEFINITION
>Case 3: ARGUMENT TYPE IS DIFFERENT THAN THE EXPECTED ARGUMENT TYPE
>1. Which of the above 3 cases are correct and which are not? Why ?

All are incorrect.  In C, every function call must match the function
definition in both number and types of arguments.  In Classic C, there
is no escape mechanism, yet printf() manages the trick: it uses an
`almost-standard' method involving <varargs.h>:

	/* complete source for a working printf() */

	#include <stdio.h>
	#include <varargs.h>

	int printf(va_alist)
		va_dcl
	{
		char *fmt;
		int ret;
		va_list ap;

		va_start(ap);
		fmt = va_arg(ap, char *);
		ret = vfprintf(stdout, fmt, ap);
		va_end(ap);
		return ret;
	}

(The above requires that your C library include the vfprintf() function;
some do not.  If not, you are out of luck, because these same systems
lack vsprintf, which is the function everyone writing `myprint' routines
always ends up using for portability.)

In New C (i.e., implementations claiming conformance to ANSI X3.159-1989)
there is an explicit escape mechanism using <stdarg.h.:

	/* revised working printf() */

	#include <stdio.h>
	#include <stdarg.h>

	int printf(char const *fmt, ...) {
		int ret;
		va_list ap;

		va_start(ap, fmt);
		ret = vfprintf(stdout, fmt, ap);
		va_end(ap);
		return ret;
	}

The three dots in the parameter list declaration tell the compiler
`the rest of the arguments are weird, like those to printf()'.  The
compiler stops applying type checking, and may use an entirely different
calling sequence.

>2. If I want to remove any "lint" warnings, for argument number mismatch,
>   what should I do ? i.e. I need a scheme to be able to pass variable
>  number of arguments to myprint(). Also it would be nice , if I could 
>  also have an ability to  pass any "type" of arguments to myprint().

Write a myprintf() along the lines shown in the second example above.
If your `lint' does not claim conformance to ANSI X3.159-1989 (`ANSI C'),
this option will not be available.  The way to `fool' lint when using
the old-style <varargs.h> file is more complicated, and depends on
exactly which lint bugs are in your lint variant.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

ark@alice.UUCP (Andrew Koenig) (05/06/90)

In article <3697@iitmax.IIT.EDU>, thssvhj@iitmax.IIT.EDU (vijay hemraj jadhwani) writes:

> myprint(stream, fmt, a1, a2, a3, a4, a5)  /* Function definition */
> FILE *stream;
> char *fmt;
> {
> 	... some initialization and assignment ...
> 	sprintf(stream, fmt, a1, a2, a3, a4, a5);
> 			.
> 			.
> 			.
> }

> 1. Which of the above 3 cases are correct and which are not? Why ?

None of them.  The myprint() function itself is non-portable and
in fact will not work on many implementations.

> 2. If I want to remove any "lint" warnings, for argument number mismatch,
>    what should I do ? i.e. I need a scheme to be able to pass variable
>   number of arguments to myprint(). Also it would be nice , if I could 
>   also have an ability to  pass any "type" of arguments to myprint().

If you want something that works, and not just something that shuts
lint up, you must use either <varargs.h> or <stdarg.h> for an ANSI C
implementation.  You must also use vfprintf, which interfaces explicitly
with <varargs.h> or <stdarg.h>.  Example:

	#include <varargs.h>

	myprint(va_alist) va_dcl
	{
		va_list ap;
		FILE *stream;
		char *fmt;

		va_start(ap);
		stream = va_arg(ap, FILE *);
		fmt = va_arg(ap, FILE *);

		/* ... some initialization and assignment ... */

		vsprintf(stream, fmt, ap);
				
		/* and so on */
	}
-- 
				--Andrew Koenig
				  ark@europa.att.com

scjones@sdrc.UUCP (Larry Jones) (05/07/90)

In article <3697@iitmax.IIT.EDU>, thssvhj@iitmax.IIT.EDU (vijay hemraj jadhwani) writes:
> Below are the three different cases of function references (or usage).
> Case 1. ACTUAL NO. OF ARGUMENTS < NO. OF ARGUMENTS IN THE FUNC. DEFINITION
> 
> Case 2.  ACTUAL NO. OF ARGUMENTS > NO. OF ARGUMENTS IN THE FUNC. DEFINITION
> 
> Case 3: ARGUMENT TYPE IS DIFFERENT THAN THE EXPECTED ARGUMENT TYPE
> 
> Questions -
> 1. Which of the above 3 cases are correct and which are not? Why ?

None of them is correct.  The number and type of arguments in a
call MUST match the number and type in the definition.  See the
ANSI C standard.

> 2. If I want to remove any "lint" warnings, for argument number mismatch,
>    what should I do ? i.e. I need a scheme to be able to pass variable
>   number of arguments to myprint(). Also it would be nice , if I could 
>   also have an ability to  pass any "type" of arguments to myprint().

Look up <stdargs.h> or <varargs.h> and vprintf().
----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@SDRC.UU.NET
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
"You know how Einstein got bad grades as a kid?  Well MINE are even WORSE!"
-Calvin