Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > variadic function

Reply
Thread Tools

variadic function

 
 
Tim Rentsch
Guest
Posts: n/a
 
      01-25-2012
Keith Thompson <(E-Mail Removed)> writes:

> [snip]
>
> If the standard did have the requirement you mention: "Do not call
> va_end after va_start unless va_arg has been called to process
> every argument in the calling sequence", what great inconvenience
> would it cause?


The problem is it requires us to know things that we may
not know, namely, the number and types of arguments remaining.
Even if a motivating example isn't immediately obvious, that's
a chilling prospect.
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      01-25-2012
Tim Rentsch <(E-Mail Removed)> writes:
> Keith Thompson <(E-Mail Removed)> writes:
>
>> [snip]
>>
>> If the standard did have the requirement you mention: "Do not call
>> va_end after va_start unless va_arg has been called to process
>> every argument in the calling sequence", what great inconvenience
>> would it cause?

>
> The problem is it requires us to know things that we may
> not know, namely, the number and types of arguments remaining.
> Even if a motivating example isn't immediately obvious, that's
> a chilling prospect.


The quoted discussion was a while ago, but I think what I had in mind is
that calling va_end "too soon" would have undefined behavior. For
example (assuming printf uses the <stdarg.h> mechanism), this:

printf("%s\n", "arg1", "ignored");

has well defined behavior; with the hypothetical rule, its behavior
would be undefined. If the language were changed in this way, no
implementations would have to change; the existing behavior would still
be conforming.

I do not advocate such a change; I was merely speculating on the
consequences if the language had been defined that way from the
beginning (or at least from 1989). As I wrote before, passing excess
arguments to a variadic function is almost certainly a programming
error; making such a call's behavior undefined would not be a great
burden.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
Tim Rentsch
Guest
Posts: n/a
 
      02-01-2012
Keith Thompson <(E-Mail Removed)> writes:

> Tim Rentsch <(E-Mail Removed)> writes:
>> Keith Thompson <(E-Mail Removed)> writes:
>>
>>> [snip]
>>>
>>> If the standard did have the requirement you mention: "Do not call
>>> va_end after va_start unless va_arg has been called to process
>>> every argument in the calling sequence", what great inconvenience
>>> would it cause?

>>
>> The problem is it requires us to know things that we may
>> not know, namely, the number and types of arguments remaining.
>> Even if a motivating example isn't immediately obvious, that's
>> a chilling prospect.

>
> The quoted discussion was a while ago, but I think what I had in mind is
> that calling va_end "too soon" would have undefined behavior. For
> example (assuming printf uses the <stdarg.h> mechanism), this:
>
> printf("%s\n", "arg1", "ignored");
>
> has well defined behavior; with the hypothetical rule, its behavior
> would be undefined.


That's an issue right there. We are taking a statement that
has defined behavior now and changing the language so it has
undefined behavior. Don't you see a problem with that?

> If the language were changed in this way, no
> implementations would have to change; the existing behavior would still
> be conforming.


Of course it would, because when there is undefined behavior
any behavior whatsoever is conforming. Implementations might
not be affected, but the semantics of programs are greatly
affected.


> I do not advocate such a change; I was merely speculating on the
> consequences if the language had been defined that way from the
> beginning (or at least from 1989). As I wrote before, passing excess
> arguments to a variadic function is almost certainly a programming
> error; making such a call's behavior undefined would not be a great
> burden.


Under the current rule, it is possible (to give one example) to
write 'printf()' in a way that is portable across different
implementations, doing all output with 'putchar()', and that works
for calls like the one above. Under the revised rule, it isn't.

The phrasing of your last sentence suggests that the notion of
"excess arguments" is well-defined, and that when it is
well-defined it's okay either to do the additional work necessary
to collect them (when it can be determined how to do so) or
accept that any such calls will result in undefined behavior
(when it cannot be so determined). I think that's nuts. More
specifically, I think the first part is wrong -- there are cases
where the number of arguments that should be processed depends on
other program state that is simply unknowable at the call site --
and the second part is misguided -- functions that complete their
task successfully should neither have to do more work to collect
"extra" arguments nor be obliged to transgress into a domain of
undefined behavior just because "extra" arguments were supplied.
I see no reason to accept any additional programming burden
along these lines, especially since allowing such cases to be
undefined behavior produces no evident benefit.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      02-01-2012
Tim Rentsch <(E-Mail Removed)> writes:
> Keith Thompson <(E-Mail Removed)> writes:
>> Tim Rentsch <(E-Mail Removed)> writes:
>>> Keith Thompson <(E-Mail Removed)> writes:
>>>> [snip]
>>>>
>>>> If the standard did have the requirement you mention: "Do not call
>>>> va_end after va_start unless va_arg has been called to process
>>>> every argument in the calling sequence", what great inconvenience
>>>> would it cause?
>>>
>>> The problem is it requires us to know things that we may
>>> not know, namely, the number and types of arguments remaining.
>>> Even if a motivating example isn't immediately obvious, that's
>>> a chilling prospect.

>>
>> The quoted discussion was a while ago, but I think what I had in mind is
>> that calling va_end "too soon" would have undefined behavior. For
>> example (assuming printf uses the <stdarg.h> mechanism), this:
>>
>> printf("%s\n", "arg1", "ignored");
>>
>> has well defined behavior; with the hypothetical rule, its behavior
>> would be undefined.

>
> That's an issue right there. We are taking a statement that
> has defined behavior now and changing the language so it has
> undefined behavior. Don't you see a problem with that?


I would certainly see a problem with that if that were what I suggested.
I'm not talking about changing the language; I'm speculating about what
problems, if any, would have resulted if the language had been defined
that way from the beginning.

When C was standardized in 1989, it *could have* been defined so that
excess arguments cause undefined behavior. If it had, I don't believe
it would have caused any great inconvenience. (Changing it now *would*
cause great inconvenience.)

If you thought such a hypothetical is not worth discussion, I would have
no argument. But you obviously do think it's worth discussion.

>> If the language were changed in this way, no
>> implementations would have to change; the existing behavior would still
>> be conforming.

>
> Of course it would, because when there is undefined behavior
> any behavior whatsoever is conforming. Implementations might
> not be affected, but the semantics of programs are greatly
> affected.


Yes. (Only the behavior of programs that pass excess arguments would be
affected; in my hypothetical situation, such programs probably wouldn't
have been written in the first place.)

>> I do not advocate such a change; I was merely speculating on the
>> consequences if the language had been defined that way from the
>> beginning (or at least from 1989). As I wrote before, passing excess
>> arguments to a variadic function is almost certainly a programming
>> error; making such a call's behavior undefined would not be a great
>> burden.

>
> Under the current rule, it is possible (to give one example) to
> write 'printf()' in a way that is portable across different
> implementations, doing all output with 'putchar()', and that works
> for calls like the one above. Under the revised rule, it isn't.


How so? An implementation that satisfies the current rule would also
satisfy the hypothetical rule. In hypothetical-C, the call's behavior
is undefined; it might as well do exactly what it does under the current
rule.

> The phrasing of your last sentence suggests that the notion of
> "excess arguments" is well-defined,


An "excess argument" to a variadic function is one for which va_arg() is
not invoked before the function calls va_end().

To put it another way, in hypothetical-C, the behavior of calling
va_end() without having called va_arg() for all the actual arguments is
undefined.

> and that when it is
> well-defined it's okay either to do the additional work necessary
> to collect them (when it can be determined how to do so) or
> accept that any such calls will result in undefined behavior
> (when it cannot be so determined). I think that's nuts. More
> specifically, I think the first part is wrong -- there are cases
> where the number of arguments that should be processed depends on
> other program state that is simply unknowable at the call site --


Ok, that might be an interesting point.

Do you suggest that there are *realistic* cases where a call to a
variadic function passes N arguments, and the function itself processes
fewer than N arguments, and where this does not indicate a logical error
in the program?

Now that you mention it, I can imagine such cases (I didn't think of any
before). For example:

const char *format_string;
if (verbose) {
format_string = "%d (%s)\n";
}
else {
format_string = "%d\n";
}
printf(format_string, num, str);

But *if* the hypothetical rule I discussed had been in the language from
the beginning, programmers just wouldn't write code like the above. It
wouldn't be that hard to write two printf calls.

I believe this would have been a minor inconvenience, rarely
encountered.

> and the second part is misguided -- functions that complete their
> task successfully should neither have to do more work to collect
> "extra" arguments nor be obliged to transgress into a domain of
> undefined behavior just because "extra" arguments were supplied.
> I see no reason to accept any additional programming burden
> along these lines, especially since allowing such cases to be
> undefined behavior produces no evident benefit.


I can imagine an implementation where a variadic function that
fails to consume all its arguments might cause Bad Things To Happen.
For example, each invocation of va_arg() might pop the corresponding
argument off the stack; failing to do so might leave the stack in an
inconsistent state. It could have much the same effect as passing
two arguments to a non-variadic function with one parameter (say,
by casting a function pointer to an inappropriate type), which has
undefined behavior in C as it's currently defined.

That's probably the scenario I had in mind when I suggested the
hypothetical rule several months ago.

Of course since C does define the behavior in such cases, no C
conforming implementation can behave this way.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      02-01-2012
On 02/01/2012 12:50 AM, Keith Thompson wrote:
....
> Do you suggest that there are *realistic* cases where a call to a
> variadic function passes N arguments, and the function itself processes
> fewer than N arguments, and where this does not indicate a logical error
> in the program?


Yes: each of the arguments indicates a place to search for something;
the function processes the arguments in turn until it's found what its
searching for, ignoring any remaining arguments.
--
James Kuyper
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      02-01-2012
On 2/1/2012 12:50 AM, Keith Thompson wrote:
>[...]
> Do you suggest that there are *realistic* cases where a call to a
> variadic function passes N arguments, and the function itself processes
> fewer than N arguments, and where this does not indicate a logical error
> in the program?


void logmessage(const char *format, ...) {
if (logstream != NULL) {
va_list ap;
va_start(ap, format);
vfprintf(logstream, format, ap);
va_end(ap);
} else {
fputs("Logical error! (?)\n", stderr);
}
}

--
Eric Sosman
(E-Mail Removed)d
 
Reply With Quote
 
Willem
Guest
Posts: n/a
 
      02-01-2012
Keith Thompson wrote:
) Do you suggest that there are *realistic* cases where a call to a
) variadic function passes N arguments, and the function itself processes
) fewer than N arguments, and where this does not indicate a logical error
) in the program?

In SQL, there is a function calles 'coalesce' which returns its first
non-NULL argument. It doesn't need to process the remaining arguments.

) I can imagine an implementation where a variadic function that
) fails to consume all its arguments might cause Bad Things To Happen.
) For example, each invocation of va_arg() might pop the corresponding
) argument off the stack; failing to do so might leave the stack in an
) inconsistent state. It could have much the same effect as passing
) two arguments to a non-variadic function with one parameter (say,
) by casting a function pointer to an inappropriate type), which has
) undefined behavior in C as it's currently defined.

Are you sure about that?
I thought that was allowed and the second argument was simply ignored.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      02-01-2012
On 2/1/2012 00:50, Keith Thompson wrote:
>
> Ok, that might be an interesting point.
>
> Do you suggest that there are *realistic* cases where a call to a
> variadic function passes N arguments, and the function itself processes
> fewer than N arguments, and where this does not indicate a logical error
> in the program?
>


I don't know if the following might qualify (please forgive any minor
errors):

int first_nonzero_value(int count, ...) {
va_list varargs;
int test;

va_start(varargs, count);
while (count--) {
test = va_arg(varargs, int);
if (test)
break;
continue;
}
va_end(varargs);
return test;
}

--
"The stationery store has moved. Aaargh!"
 
Reply With Quote
 
Ben Pfaff
Guest
Posts: n/a
 
      02-01-2012
Shao Miller <(E-Mail Removed)> writes:

> On 2/1/2012 00:50, Keith Thompson wrote:
>>
>> Ok, that might be an interesting point.
>>
>> Do you suggest that there are *realistic* cases where a call to a
>> variadic function passes N arguments, and the function itself processes
>> fewer than N arguments, and where this does not indicate a logical error
>> in the program?
>>

>
> I don't know if the following might qualify (please forgive any minor
> errors):
>
> int first_nonzero_value(int count, ...) {
> va_list varargs;
> int test;
>
> va_start(varargs, count);
> while (count--) {
> test = va_arg(varargs, int);
> if (test)
> break;
> continue;
> }
> va_end(varargs);
> return test;
> }


How about this:

int max(int count, ...) {
int max = INT_MIN;
va_list args;

va_start(args, count);
do {
int value = va_arg(args, int);
if (value > max)
max = value;
} while (--count && max != INT_MAX);
va_end(args);

return max;
}
--
"Your correction is 100% correct and 0% helpful. Well done!"
--Richard Heathfield
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      02-01-2012
Willem <(E-Mail Removed)> writes:
> Keith Thompson wrote:
> ) Do you suggest that there are *realistic* cases where a call to a
> ) variadic function passes N arguments, and the function itself processes
> ) fewer than N arguments, and where this does not indicate a logical error
> ) in the program?
>
> In SQL, there is a function calles 'coalesce' which returns its first
> non-NULL argument. It doesn't need to process the remaining arguments.
>
> ) I can imagine an implementation where a variadic function that
> ) fails to consume all its arguments might cause Bad Things To Happen.
> ) For example, each invocation of va_arg() might pop the corresponding
> ) argument off the stack; failing to do so might leave the stack in an
> ) inconsistent state. It could have much the same effect as passing
> ) two arguments to a non-variadic function with one parameter (say,
> ) by casting a function pointer to an inappropriate type), which has
> ) undefined behavior in C as it's currently defined.
>
> Are you sure about that?
> I thought that was allowed and the second argument was simply ignored.


You're right. The context of the quoted paragraph was a hypothetical
version of C that doesn't permit invoking va_end() before invoking
va_arg() for all actual arguments. An implementation as I described
could implement such a hypothetical C, and implementing it *might* be
more convenient than implementing something that handles C as it's
actually defined. It would not be a conforming implementation of C as
it's actually defined.

This all started with an idle speculation of mine several months ago
about whether, if C had *originally* required all variadic arguments to
be processed, it would create any great inconvenience. At the time, I
didn't have any examples where it would be a problem. Several such
examples have now been offered.

The C89 committee *could* have imposed such a requirements, and if they
had, programmers would have managed, but there are some valid techniques
that couldn't be used.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Call again a variadic function (... variable number of arguments)with same arguments that its variadic wrapper moreau.steve@gmail.com C Programming 3 12-31-2008 07:13 AM
variadic function calling variadic function goldfita@signalsguru.net C Programming 5 05-03-2006 05:23 PM
Using variadic functions within variadic functions pinkfloydhomer@gmail.com C Programming 2 02-27-2006 05:47 AM
Variadic functions calling variadic functions with the argument list, HLL bit shifts on LE processors Ross A. Finlayson C Programming 19 03-10-2005 03:57 AM
is casting a variadic function to a non-variadic one legal? Colin Walters C Programming 2 02-13-2004 10:55 PM



Advertisments