Alf
Fri Jul 18 17:52:52 CDT 2008
* Liviu:
> "Alf P. Steinbach" <alfps@start.no> wrote
>> * Liviu:
>>> "Alf P. Steinbach" <alfps@start.no> wrote
>>>> * Igor Tandetnik:
>>>>> Alf P. Steinbach <alfps@start.no> wrote:
>>>>>> * Igor Tandetnik:
>>>>>>> printf("%d", 1, 2);
>>>> For what it's worth the above example (1) has undefined behavior
>>> Nope, behavior is both defined and expected (prints 1, excess
>>> arguments
>>> are evaluated but ignored).
>> In C99. Thanks, I didn't know. Do you have C89 standard?
>
> Don't have it handy, but if google's
>
http://rm-f.net/~orange/devel/specifications/c89-draft.html#4.9.6.1
> is to be trusted, then it's the same:
>
> | If there are insufficient arguments for the format, the behavior is
> | undefined. If the format is exhausted while arguments remain, the
> | excess arguments are evaluated (as always) but are otherwise ignored.
>
>>> You might be thinking at "printf("%d");" but even in that case the
>>> "undefinededness" is particular to printf, and has nothing to do with
>>> calling conventions for variadic functions in general.
>> It had to do with a minor point that Igor may or may not have been
>> trying to make, who knows since evidently he doesn't mean what he
>> writes.
>
> I'll go on a limb here ;-) but I trust Igor meant exactly what he wrote:
>
> | With stdcall, the function is responsible for removing its parameters
> | from the stack. To do this, it must know how many parameters there
> | are, and thus cannot take variable number of parameters.
>
>> But just to address what you say, although unrelated to original
>> context: I'm sorry, but that's incorrect, i.e. contrary to your claim
>> the behavior of printf has to do with calling conventions for variadic
>> functions in general.
>>
>> C99 printf directly supports a functionally limited and generally
>> inefficient calling convention (C-style) and for printf, makes the
>> case that that convention doesn't handle, undefined behavior.
>
> Sorry, but I don't follow.
See below.
> The only undefined behavior mentioned there
> is when the caller passes _fewer_ arguments than expected from the
> format string, and that's because of printf internals.
No, that's not because of printf internals, that's because with the C calling
convention printf has no way of checking that there are indeed enough arguments.
> On the other
> hand, the standard explicitly states that excess parameters are
> ignored, so it's painfully obvious that printf couldn't possibly clear
> the stack after itself based on what the format string says.
Unfortunately, yes.
> Imagine for a moment that you'd be writing the __stdcall printf(const
> char *, ...) code. At the point your code would be entered, everything
> would look _exactly_ the same when the function is called in either of
> these ways:
>
> printf("%d", 1);
> printf("%d", 1, 2);
>
> How would you code your printf so that it pops the right number of bytes
> off the stack in each case?
No problem. The number of bytes is passed in any way the compiler deems
suitable, since printf is declared with "...". This is the same as the compiler
is free to use e.g. RVO, and really whatever it wants; you'd not say that a
stdcall function that the compiler implements with RVO is not stdcall?
>> I replied originally to Igor by posting complete C++ plus assembly
>> language code for an example of __stdcall variadic arguments.
>
> No. You just provided several overloads of the 'knurre' function which
> happened to internally share some assembly code.
So? "You just provided a car-minus-wheels plus wheels attached". How is that the
reality different from a car, just by your description being different and
focused on irrelevant details?
> If the point of the exercise was to show that passing an additional
> "number of params" into a function can allow it to pop the stack itself,
> then yes of course it's both possible and trivial. But it's not
> __stdcall, since there is no presumption in __stdcall that such a
> "number of params" argument must exist.
The __stdcall convention does not address what arguments are used for.
It's meaningless to say that void foo(char ch), when compiled as stdcall, isn't
stdcall just because that argument is used for output or whatever, and that that
argument usage is not prescribed by stdcall.
And it's meaningless to say that an RVO-optimized function isn't stdcall (an
RVO-optimized function may have an extra hidden compiler-generated argument).
However by your reasoning it can't be. I don't really think you believe this
idiocy yourself, I think you're just putting it forward as rhetoric.
Cheers, & hth.,
- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?