I am not a fan of variable argument functions either. I came to C from C++
originally and since I liked function overloading, I figured I'd try the
concept in C. Then I ran into all the difficulties you've described.

What I went with in the rare cases where I did use them was the 'sentinel'
concept. One of my college professors liked it and it stuck with me.
Basically, you designate a special value (i.e. NULL) as the list terminator
(aka sentinel). Then the doStuff() function processes the list until it
hits the sentinel.

There are drawbacks with that approach as well. Sometimes it's not really
possible to find a special value in the data type range that can be reserved
for the sentinel. Another drawback is that the burden is on the invoker to
include the sentinel every time he uses the function.
In my case I was originally the only invoker, so it wasn't a big deal.
Later on though, this function became a common function and a lot of
developers started using it. I think the reason we never ran into problems
with it is that they tend to clone-and-go, so when they clone the original
code, they're lucky to include the sentinel value as well.

As far as I know, this is the issue with all C implementations, not just the
IBM i.

For the relative 'safety' it provides, I actually like your #1 approach.
That's how main() works and for most C developers it wouldn't be a big leap
to understand the concept (i.e. for the consumers of your doStuff()
function).

Elvis


Celebrating 11-Years of SQL Performance Excellence on IBM i, i5/OS and
OS/400
www.centerfieldtechnology.com


-----Original Message-----
Subject: [C400-L] optional arguments in C

My first questions in I don't know how long ...

I've used the various va_xxxx macros previously to handle passing
varying arguments to things like vsprintf and vsnprintf and I've used
them to handle multiple parameters but always when one of the prior
fixed arguments indicated how many extra arguments are expected. For
example, in the format string for the printf series of procedures the
number of substitution values indicates the number of expected
arguments.

I've just been doing a bunch of stuff with C and thought it would be
useful to make use of optional parameters on various procedure
interfaces. I defined a bunch of procedures with fixed parameters
followed by an ellipsis to indicate optional parameters. In each
procedure I declared a va_list and used va_start, va_arg, va_end to
extract the additional parameters.

However, I find this to be unsafe in practice because the C compiler
does not provide a way to terminate an argument list. Thus if a
function is defined as:

int doStuff( int p1, ... )

where ... could be any number of parameters there is no way for the
callee to KNOW whether a given parameter was actually passed. In the
callee we could code:

va_list ap;
int p2 = 0;
char * p3 = NULL;
double p4 = 0.0;

va_start( ap, p1 );
p2 = va_arg( ap, int );
p3 = va_arg( ap, char * );
p4 = va_arg( ap, double );

If the caller invokes doStuff and specifies all 3 additional
arguments everything works as expected. However if doStuff is invoked
with fewer than the full complement of parameters whether the code
works is entirely due to what happens to be on the stack at the time
of the call. Even if the caller does:

rc = doStuff( 100 );

p2, p3, and p4 may be set to values that are entirely incorrect due
to pointers or values existing on the stack after p1 from a prior
call to some other unrelated procedure.

None of my C references mention this potential problem. It sort of
makes sense given how little the C compiler actually does for the
developer. The various references always talk about a "varying number
of arguments" and never about "optional" parameters. None of the
references explicitly state that the caller MUST provide some means
for the callee to know how many parameters to expect. For the C
library family of printf functions this is handled implicitly by the
format string. The number of %-prefixed substitution values indicates
the number of parameters to expect. I am aware that passing fewer
arguments than substitution values will result in unpredictable
behaviour but I had not followed that through to its obvious conclusion.

I hesitate to use the word reasonable regarding anything to do with
C--such an excremental language-- but surely this is not reasonable
behaviour?

Is this how all C compilers work or only the OS/400 one?

Is this a side-effect of V5 and above using the AIX C compiler code-
base or would this behaviour occur in the previous native C compiler?

I have always thought that requiring at least one fixed parameter
prior to the variable argument list was a remarkably short-sighted
design.

Net effect of this behaviour is that C does not support "optional"
parameters.

Seems my only solutions are:

1) Include a fixed parameter for "number of additional parameters"
or
2) Drop any attempted support for "optional" parameters and require

the caller to pass NULL or 0 when they don't want to pass a real value.

Both of these approaches result in ugly and clumsy interfaces.

Can anyone suggest a better solution apart from the obvious one of
using a language with better support for optional parameters such as
RPG IV?

Regards,
Simon Coulter.




This thread ...

Follow-Ups:
Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2019 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available here. If you have questions about this, please contact [javascript protected email address].