By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,147 Members | 1,347 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,147 IT Pros & Developers. It's quick & easy.

printf doubt

P: n/a
Hi, there is some kind of difference in these two statements?

float num = 154.87;
printf("There is : $0.0f",num);
and
float num = 154.87;
printf("There is : $f",num);

Jul 11 '06 #1
Share this Question
Share on Google+
28 Replies


P: n/a
dutche said:
Hi, there is some kind of difference in these two statements?

float num = 154.87;
printf("There is : $0.0f",num);
and
float num = 154.87;
printf("There is : $f",num);
Yes. (We will assume that the '$' character is in the execution character
set.)

The first of your examples will print:

There is : $0.0f

The second will print:

There is : $f

These are different outputs.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 11 '06 #2

P: n/a

Richard Heathfield escreveu:
dutche said:
Hi, there is some kind of difference in these two statements?

float num = 154.87;
printf("There is : $0.0f",num);
and
float num = 154.87;
printf("There is : $f",num);

Yes. (We will assume that the '$' character is in the execution character
set.)

The first of your examples will print:

There is : $0.0f

The second will print:

There is : $f

These are different outputs.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)


Sorry I made a mistake :)

float num = 154.87;
printf("There is : $%0.0f",num);

and

float num = 154.87;
printf("There is : $%f",num);

Jul 11 '06 #3

P: n/a
On 2006-07-11, dutche <du****@gmail.comwrote:
Hi, there is some kind of difference in these two statements?

float num = 154.87;
printf("There is : $0.0f",num);
and
float num = 154.87;
printf("There is : $f",num);
Run them, and you'll note that one will print "There is : $0.0f" and
other other will print "There is : $f", neither of which will have a
newline*

* Actually, on a lot of systems it won't print at all, because you're
missing a newline.

You need to read a good beginner's C book.

--
Andrew Poelstra <http://www.wpsoftware.net/projects/>
To email me, use "apoelstra" at the above domain.
"You people hate mathematics." -- James Harris
Jul 11 '06 #4

P: n/a
dutche said:

<snip>
>
float num = 154.87;
printf("There is : $%0.0f",num);
This will print the value in at least 0 (first 0!) columns but possibly
more, and with a precision of 0 (second 0) decimal places. The number is
"rounded to the appropriate number of digits", as the Standard puts it. So
in this case it'll display 155 (because that's closer than 154).
and

float num = 154.87;
printf("There is : $%f",num);
This will just print the value, to default precision. On my implementation
it gives 154.869995 as the result.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 11 '06 #5

P: n/a
On 2006-07-11, Andrew Poelstra <ap*******@localhost.localdomainwrote:
On 2006-07-11, dutche <du****@gmail.comwrote:
>Hi, there is some kind of difference in these two statements?

float num = 154.87;
printf("There is : $0.0f",num);

You need to read a good beginner's C book.
Never mind; I thought you confused `$' and `%', but according to your
other post, you just forgot to type `%', which is an understandable
mistake (because the characters are right beside each other on a US
keyboard, and you'd already typed one).

--
Andrew Poelstra <http://www.wpsoftware.net/projects/>
To email me, use "apoelstra" at the above domain.
"You people hate mathematics." -- James Harris
Jul 11 '06 #6

P: n/a
Richard Heathfield wrote:
dutche said:

<snip>

float num = 154.87;
printf("There is : $%0.0f",num);

This will print the value in at least 0 (first 0!) columns but possibly
more, and with a precision of 0 (second 0) decimal places. The number is
"rounded to the appropriate number of digits", as the Standard puts it. So
in this case it'll display 155 (because that's closer than 154).
and

float num = 154.87;
printf("There is : $%f",num);

This will just print the value, to default precision.
More precisely, it will print the value as if a precision of 6 had been
specified (ignoring the fact that no newline is present).

Robert Gamble

Jul 11 '06 #7

P: n/a

"dutche" <du****@gmail.comwrote in message
news:11**********************@h48g2000cwc.googlegr oups.com...
Hi, there is some kind of difference in these two statements?

float num = 154.87;
printf("There is : $0.0f",num);
and
float num = 154.87;
printf("There is : $f",num);
Yes. The first one will print:
There is : $0.0f
and the second will print:
There is : $f

And without a newline, it is possible that neither will show up.
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project
Jul 11 '06 #8

P: n/a
On Tue, 11 Jul 2006 14:14:55 +0000, Richard Heathfield
<in*****@invalid.invalidwrote:
>dutche said:
>Hi, there is some kind of difference in these two statements?

float num = 154.87;
printf("There is : $0.0f",num);
and
float num = 154.87;
printf("There is : $f",num);

Yes. (We will assume that the '$' character is in the execution character
set.)

The first of your examples will print:

There is : $0.0f

The second will print:

There is : $f

These are different outputs.
Does not the presence of a superfluous argument lead to undefined
behavior?
Remove del for email
Jul 11 '06 #9

P: n/a
Barry Schwarz <sc******@doezl.netwrites:
Does not the presence of a superfluous argument lead to undefined
behavior?
No. From C99 7.19.6.1 "The fprintf function":

If the format is exhausted while arguments remain, the
excess arguments are evaluated (as always) but are otherwise
ignored.
--
"You call this a *C* question? What the hell are you smoking?" --Kaz
Jul 11 '06 #10

P: n/a
Barry Schwarz said:

<snip>
>
Does not the presence of a superfluous argument lead to undefined
behavior?
No. The relevant C89 draft wording is:

"If the format is exhausted while arguments remain, the excess
arguments are evaluated (as always) but are otherwise ignored."

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 11 '06 #11

P: n/a
In article <Sv********************@bt.com>
Richard Heathfield <in*****@invalid.invalidwrote:
>dutche said:
>float num = 154.87;
printf("There is : $%0.0f",num);
>This will print the value in at least 0 (first 0!) columns ...
Aha, a rare Richard Heathfield error! :-)

In a printf conversion, the "0" character is a *flag*, not a field
width, unless:

- you are already working on a field width, or
- you are already working on a precision

(and possibly if you use various extensions as well). For instance,

printf("%040d\n", 12);

prints "0000000000000000000000000000000000000012\n", while:

printf ("%40d\n", 12);

prints " 12\n".

A zero flag is allowed with %f conversions, with the obvious meaning
(so printing 0.5 with %012.6f produces "00000.500000"; note that the
field width includes the decimal-point character).
>but possibly more, and with a precision of 0 (second 0) decimal
places.
Note that, for %f format, if no precision is specified, a default
value of 6 is assumed. So:

printf("%f\n", val);

and:

printf("%.6f\n", val);

have identical meanings.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jul 11 '06 #12

P: n/a
Andrew Poelstra <ap*******@localhost.localdomainwrites:
On 2006-07-11, dutche <du****@gmail.comwrote:
>Hi, there is some kind of difference in these two statements?

float num = 154.87;
printf("There is : $0.0f",num);
and
float num = 154.87;
printf("There is : $f",num);

Run them, and you'll note that one will print "There is : $0.0f" and
other other will print "There is : $f", neither of which will have a
newline*

* Actually, on a lot of systems it won't print at all, because you're
missing a newline.
Actually, we don't know that he's missing a newline. He's only showed
us a couple of small code fragments, not an entire program. If
putchar('\n') or equivalent is executed later on, he's fine (at least
as far as trailing newlines are concerned).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 11 '06 #13

P: n/a
Barry Schwarz wrote:
On Tue, 11 Jul 2006 14:14:55 +0000, Richard Heathfield
<in*****@invalid.invalidwrote:
>dutche said:
>>Hi, there is some kind of difference in these two statements?

float num = 154.87;
printf("There is : $0.0f",num);
<snip>
Does not the presence of a superfluous argument lead to undefined
behavior?
No, you are explicitly allowed to pass extra arguments to printf. The
standard states "If the format is exhausted while arguments remain, the
excess arguments are evaluated (as always) but are otherwise ignored."
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Jul 11 '06 #14

P: n/a
Chris Torek said:
In article <Sv********************@bt.com>
Richard Heathfield <in*****@invalid.invalidwrote:
>>dutche said:
>>float num = 154.87;
printf("There is : $%0.0f",num);
>>This will print the value in at least 0 (first 0!) columns ...

Aha, a rare Richard Heathfield error! :-)
I don't know whether to be annoyed or delighted. :-)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 11 '06 #15

P: n/a
On Tue, 11 Jul 2006 10:09:17 -0700, Ben Pfaff <bl*@cs.stanford.edu>
wrote:
>Barry Schwarz <sc******@doezl.netwrites:
>Does not the presence of a superfluous argument lead to undefined
behavior?

No. From C99 7.19.6.1 "The fprintf function":

If the format is exhausted while arguments remain, the
excess arguments are evaluated (as always) but are otherwise
ignored.
I wonder how systems which push return addresses and arguments on the
same stack, like the old 6502, manage this. Obviously, fprintf will
not pop the superfluous arguments off the stack since it doesn't even
know about them.
Remove del for email
Jul 12 '06 #16

P: n/a
Barry Schwarz <sc******@doezl.netwrites:
On Tue, 11 Jul 2006 10:09:17 -0700, Ben Pfaff <bl*@cs.stanford.edu>
wrote:
>>Barry Schwarz <sc******@doezl.netwrites:
>>Does not the presence of a superfluous argument lead to undefined
behavior?

No. From C99 7.19.6.1 "The fprintf function":

If the format is exhausted while arguments remain, the
excess arguments are evaluated (as always) but are otherwise
ignored.

I wonder how systems which push return addresses and arguments on the
same stack, like the old 6502, manage this.
What systems use separate stacks for return addresses and
arguments? I am not aware of any in the modern world, so it
would be educational to hear about them. Such a system might be
more resistant to "stack smashing" buffer overflow attacks, for
one thing.
Obviously, fprintf will not pop the superfluous arguments off
the stack since it doesn't even know about them.
A common convention is for the callee to pop off the return
address and leave the arguments on the stack. The caller then
pops the arguments.
--
"Your correction is 100% correct and 0% helpful. Well done!"
--Richard Heathfield
Jul 12 '06 #17

P: n/a
Barry Schwarz wrote:
I wonder how systems which push return addresses and arguments on the
same stack, like the old 6502,
and x86, and sparc, ...
manage this. Obviously, fprintf will not pop the superfluous arguments
off the stack since it doesn't even know about them.
The caller cleans up the stack. For example, the caller might
push the arguments and return address, then call the function,
then rewind the stack pointer.

Jul 12 '06 #18

P: n/a
Barry Schwarz (in g1********************************@4ax.com) said:

| I wonder how systems which push return addresses and arguments on
| the same stack, like the old 6502, manage this. Obviously, fprintf
| will not pop the superfluous arguments off the stack since it
| doesn't even know about them.

From out of the mists of time I heard a raspy voice whisper: "Dope
vectors..." In some environments they were used exclusively to
describe arrays; and on others to describe and point to call
parameters.

--
Morris Dovey
DeSoto Solar
DeSoto, Iowa USA
http://www.iedu.com/DeSoto
Jul 12 '06 #19

P: n/a
Barry Schwarz <sc******@doezl.netwrites:
On Tue, 11 Jul 2006 10:09:17 -0700, Ben Pfaff <bl*@cs.stanford.edu>
wrote:
>>Barry Schwarz <sc******@doezl.netwrites:
>>Does not the presence of a superfluous argument lead to undefined
behavior?

No. From C99 7.19.6.1 "The fprintf function":

If the format is exhausted while arguments remain, the
excess arguments are evaluated (as always) but are otherwise
ignored.

I wonder how systems which push return addresses and arguments on the
same stack, like the old 6502, manage this. Obviously, fprintf will
not pop the superfluous arguments off the stack since it doesn't even
know about them.
Presumably the caller has to pop the arguments (or pass an extra
implicit argument so the callee knows what to pop).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 12 '06 #20

P: n/a

In article <87************@benpfaff.org>, Ben Pfaff <bl*@cs.stanford.eduwrites:
>
What systems use separate stacks for return addresses and
arguments? I am not aware of any in the modern world, so it
would be educational to hear about them.
The ever-lovin' AS/400 (now iSeries) OPM (Original Program Model)
appears to, based on the documentation for MI, the pseudo-assembly
language supplied with OS/400. (I say "appears to" because I'm
taking this from the somewhat-sparse documentation, my own
recollections, and what I've read from IBM insiders on Usenet; I'm no
expert on AS/400 internals.)

The first thing to remember about the AS/400, for programs running
in normal iOS mode (and not PACE or NT or Linux or whatever else
might be supported these days), is the "single-level store". Every
object in the machine has one address in a single 64-bit virtual
address space. (Pointers are actually 128 bits because they contain
a bunch of other information.) There's no per-process virtual
addressing.

Thus in a sense return addresses and parameters are in the "same"
area, but only because there's only one area. They probably won't
be contiguous, and it's not really a stack.

Security is provided by a combination of trusted compilation from
intermediate code into the native instruction stream, the
underlying capability architecture, and some hardware protections,
though the last play less of a role than in more typical process-
virtual-addressing systems.

MI (and the languages based on it such as OPM COBOL) supports three
call operations:

Call Internal (CALLI)
Call External (CALLX)
Call Program with Variable Length Argument List (CALLPGMV)

(There's also "program activation", which is sort of like dynamic
loading without invoking; and "transfer control", which is like
the exec system call in Unix; but I'll ignore those here.)

For an internal call, which creates a subactivation within the
current activation (the equivalent of a "normal call" on one of
those puny regular computers), the calling routine provides an
instruction pointer as the third operand, and the return address
is placed in that pointer. The called routine receives this
pointer and uses it as the operand of a Branch (B) instruction
to return. (Yes, an internal return is just a branch.)

Said instruction pointer must be allocated from (what passes for)
the heap or (what passes for) static data by the calling routine.

Paramerers, on the other hand, are specified an an operand list (OL)
pointer which is another operand of the CALLI operation. The called
routine should declare an operand list corresponding to the
parameters it expects to receive. When it's called, it can reference
those parameters, which will create a temporary mapping in the form
of space pointers to the parameter objects (all parameters are passed
by reference).

External calls are similar, except that a new activation is created
using the specified program object (which is sort of like a program
or shared library on less-interesting systems), and control is passed
to its program entry procedure (if it's a bound program) or external
entry point (if it's non-bound). It also takes an OL as an operand,
but rather than a return instruction pointer, the calling routine can
provide an optional "instruction definition list", which is basically
a list of addresses that the called program can return to. So the
called program doesn't have to return to the place from whence it was
called. Fun!

An external-called program returns using the External Return (RETX)
opcode. If the called program is non-bound and the caller supplied
a return list, the called program can provide an integer operand
that's an index into the return list to say which return point to
return to.

There are a bunch of other differences between external calls to
bound and non-bound programs, but I'll gloss over them.

Call Program with Variable Length Argument List is like CALLX except
that it takes an array of parameters and a count, and it omits the
list of possible return locations (the called program has to return
to the place it was called from).

Of course, these days not many people use OPM; they've mostly
switched to ILE, the Integrated Language Environment. ILE does use a
call stack and supports pass-by-value (and pass-by-reference and
pass-by- reference-to-temporary-copy), though it's still rather more
complicated than just the sort of move-and-decrement that's typical
of less-CISCy architectures.

These and many more intriguing details can be found at:

http://publib.boulder.ibm.com/infoce...v5r3/index.jsp

(Requires Javascript and all manner of such things.) Look especially
at Programming -APIs -MI Programming and Programming -Languages
-ILE Concepts.
Such a system might be
more resistant to "stack smashing" buffer overflow attacks, for
one thing.
Well, the '400 is certainly more resistant than many other platforms
to stack smashing.

--
Michael Wojcik mi************@microfocus.com

The presence of those seeking the truth is infinitely preferable to
the presence of those who think they've found it. -- Terry Pratchett
Jul 12 '06 #21

P: n/a
On Tue, 11 Jul 2006 19:13:09 -0700, Ben Pfaff <bl*@cs.stanford.edu>
wrote:
>Barry Schwarz <sc******@doezl.netwrites:
>On Tue, 11 Jul 2006 10:09:17 -0700, Ben Pfaff <bl*@cs.stanford.edu>
wrote:
>>>Barry Schwarz <sc******@doezl.netwrites:

Does not the presence of a superfluous argument lead to undefined
behavior?

No. From C99 7.19.6.1 "The fprintf function":

If the format is exhausted while arguments remain, the
excess arguments are evaluated (as always) but are otherwise
ignored.

I wonder how systems which push return addresses and arguments on the
same stack, like the old 6502, manage this.

What systems use separate stacks for return addresses and
arguments? I am not aware of any in the modern world, so it
would be educational to hear about them. Such a system might be
more resistant to "stack smashing" buffer overflow attacks, for
one thing.
I don't of any systems using separate stacks but I am familiar with
one that uses no stacks. IBM's MVS system and all its descendants
through the current z/OS use a combination linked list (for return
addresses) and pointer to pseudo-array (for arguments). Ignoring
superfluous arguments requires no action in this system since they are
always after the relevant arguments in the pseudo-array. And it is
very resistant to buffer overflow attacks but the calling convention
is only one of many reasons.
>
>Obviously, fprintf will not pop the superfluous arguments off
the stack since it doesn't even know about them.

A common convention is for the callee to pop off the return
address and leave the arguments on the stack. The caller then
pops the arguments.
An obvious solution which I'm embarrassed to admit I didn't consider
before I asked the question.
Remove del for email
Jul 12 '06 #22

P: n/a
Op Tue, 11 Jul 2006 19:13:09 -0700 schreef Ben Pfaff:
Barry Schwarz <sc******@doezl.netwrites:
>On Tue, 11 Jul 2006 10:09:17 -0700, Ben Pfaff <bl*@cs.stanford.edu>
wrote:
>>>Barry Schwarz <sc******@doezl.netwrites:

Does not the presence of a superfluous argument lead to undefined
behavior?

No. From C99 7.19.6.1 "The fprintf function":

If the format is exhausted while arguments remain, the
excess arguments are evaluated (as always) but are otherwise
ignored.

I wonder how systems which push return addresses and arguments on the
same stack, like the old 6502, manage this.

What systems use separate stacks for return addresses and
arguments? I am not aware of any in the modern world, so it
would be educational to hear about them. Such a system might be
more resistant to "stack smashing" buffer overflow attacks, for
one thing.
I think of Forth processors with code generated by a C compiler.
--
Coos
Jul 12 '06 #23

P: n/a
Ben Pfaff wrote:
What systems use separate stacks for return addresses and
arguments? I am not aware of any in the modern world, so it
would be educational to hear about them. Such a system might be
more resistant to "stack smashing" buffer overflow attacks, for
one thing.

IPF more-or-less does. The registers are saved by the RSE in one
stack, which is distinct from the "normal" application stack. And
since subroutine calls always save the return address in a register,
they get saved in the RSE stack. Parameters passed in registers also
get saved in the RSE stack, which is why I said more-or-less.

Of course that assumes that anything gets saved in the RSE stack, which
only happens when there are no more free registers.

More-or-less the same thing happens with SPARC register Windows. C on
a number of the smaller embedded processors works that way too.

And yes, separating the returns (and register saves) pretty much makes
that particular type of stack smash impossible (of course that doesn't
help if any other function pointers are stored on the data stack) .

FWIW, implementing a compiler that did this on, say x86, would be
trivial, and would add only modest overhead to each function call. You
could continue to use esp for return addresses and register saves, and
use ebp for stack frames.

Jul 13 '06 #24

P: n/a
Ben Pfaff wrote:
Barry Schwarz <sc******@doezl.netwrites:
>On Tue, 11 Jul 2006 10:09:17 -0700, Ben Pfaff <bl*@cs.stanford.edu>
wrote:
>>Barry Schwarz <sc******@doezl.netwrites:

Does not the presence of a superfluous argument lead to undefined
behavior?
No. From C99 7.19.6.1 "The fprintf function":

If the format is exhausted while arguments remain, the
excess arguments are evaluated (as always) but are otherwise
ignored.
I wonder how systems which push return addresses and arguments on the
same stack, like the old 6502, manage this.

What systems use separate stacks for return addresses and
arguments? I am not aware of any in the modern world, so it
would be educational to hear about them. Such a system might be
more resistant to "stack smashing" buffer overflow attacks, for
one thing.
>Obviously, fprintf will not pop the superfluous arguments off
the stack since it doesn't even know about them.

A common convention is for the callee to pop off the return
address and leave the arguments on the stack. The caller then
pops the arguments.
Missing the point maybe. There are some number of arguments to printf,
one of them being the format string. Let's assume a format string and
four other expressions. That's five arguments. If the format string
describes what to do with only two expressions, so be it. Only two will
be treated. But five arguments were pushed and five will be popped.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Jul 13 '06 #25

P: n/a
Joe Wright <jo********@comcast.netwrites:
Ben Pfaff wrote:
>Barry Schwarz <sc******@doezl.netwrites:
>>On Tue, 11 Jul 2006 10:09:17 -0700, Ben Pfaff <bl*@cs.stanford.edu>
wrote:

Barry Schwarz <sc******@doezl.netwrites:

Does not the presence of a superfluous argument lead to undefined
behavior?
No. From C99 7.19.6.1 "The fprintf function":

If the format is exhausted while arguments remain, the
excess arguments are evaluated (as always) but are otherwise
ignored.
I wonder how systems which push return addresses and arguments on the
same stack, like the old 6502, manage this.
What systems use separate stacks for return addresses and
arguments? I am not aware of any in the modern world, so it
would be educational to hear about them. Such a system might be
more resistant to "stack smashing" buffer overflow attacks, for
one thing.
>>Obviously, fprintf will not pop the superfluous arguments off
the stack since it doesn't even know about them.
A common convention is for the callee to pop off the return
address and leave the arguments on the stack. The caller then
pops the arguments.

Missing the point maybe. There are some number of arguments to printf,
one of them being the format string. Let's assume a format string and
four other expressions. That's five arguments. If the format string
describes what to do with only two expressions, so be it. Only two
will be treated. But five arguments were pushed and five will be
popped.
Which means that a calling convention where the callee needs to know
how many arguments were passed won't work for printf() or other
variadic functions (unless there's an extra implicit argument that
provides that information).

A C compiler *could* use such a convention for non-variadic functions,
but I think most compilers use the same convention for both (since
there was no such distinction in early C).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 13 '06 #26

P: n/a
Keith Thompson wrote:
Joe Wright <jo********@comcast.netwrites:
>Ben Pfaff wrote:
>>Barry Schwarz <sc******@doezl.netwrites:

On Tue, 11 Jul 2006 10:09:17 -0700, Ben Pfaff <bl*@cs.stanford.edu>
wrote:

Barry Schwarz <sc******@doezl.netwrites:
>
>Does not the presence of a superfluous argument lead to undefined
>behavior?
No. From C99 7.19.6.1 "The fprintf function":
>
If the format is exhausted while arguments remain, the
excess arguments are evaluated (as always) but are otherwise
ignored.
I wonder how systems which push return addresses and arguments on the
same stack, like the old 6502, manage this.
What systems use separate stacks for return addresses and
arguments? I am not aware of any in the modern world, so it
would be educational to hear about them. Such a system might be
more resistant to "stack smashing" buffer overflow attacks, for
one thing.

Obviously, fprintf will not pop the superfluous arguments off
the stack since it doesn't even know about them.
A common convention is for the callee to pop off the return
address and leave the arguments on the stack. The caller then
pops the arguments.
Missing the point maybe. There are some number of arguments to printf,
one of them being the format string. Let's assume a format string and
four other expressions. That's five arguments. If the format string
describes what to do with only two expressions, so be it. Only two
will be treated. But five arguments were pushed and five will be
popped.

Which means that a calling convention where the callee needs to know
how many arguments were passed won't work for printf() or other
variadic functions (unless there's an extra implicit argument that
provides that information).

A C compiler *could* use such a convention for non-variadic functions,
but I think most compilers use the same convention for both (since
there was no such distinction in early C).
At least one popular compiler does not. In the documentation for
Microsoft Visual Studio .NET under the description for __stdcall it says:
The __stdcall calling convention is used to call Win32 API functions.
The callee cleans the stack, so the compiler makes vararg functions
__cdecl. Functions that use this calling convention require a
function prototype.

So if the compiler is set to use __stdcall by default it will use
different calling conventions for variadic and non-variadic functions.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Jul 14 '06 #27

P: n/a
On 14 Jul 2006 09:00:57 +0200, Flash Gordon <sp**@flash-gordon.me.uk>
wrote:
>A C compiler *could* use such a convention for non-variadic functions,
but I think most compilers use the same convention for both (since
there was no such distinction in early C).

At least one popular compiler does not. In the documentation for
Microsoft Visual Studio .NET under the description for __stdcall it says:
The __stdcall calling convention is used to call Win32 API functions.
The callee cleans the stack, so the compiler makes vararg functions
__cdecl. Functions that use this calling convention require a
function prototype.
At least one compiler, Watcom C (now OpenWatcom) allows the user to
specify one of several calling conventions. In fact, I think you can
even make up your own.

--
Al Balmer
Sun City, AZ
Jul 14 '06 #28

P: n/a
Al Balmer wrote:
On 14 Jul 2006 09:00:57 +0200, Flash Gordon <sp**@flash-gordon.me.uk>
wrote:
>>A C compiler *could* use such a convention for non-variadic functions,
but I think most compilers use the same convention for both (since
there was no such distinction in early C).
At least one popular compiler does not. In the documentation for
Microsoft Visual Studio .NET under the description for __stdcall it says:
The __stdcall calling convention is used to call Win32 API functions.
The callee cleans the stack, so the compiler makes vararg functions
__cdecl. Functions that use this calling convention require a
function prototype.

At least one compiler, Watcom C (now OpenWatcom) allows the user to
specify one of several calling conventions. In fact, I think you can
even make up your own.
That would be even more interesting than MSVC++. MSVC++ doesn't let you
define your own, but it does allow you to select which of the calling
conventions to use by default (if not overridden using an MS extension).
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Jul 14 '06 #29

This discussion thread is closed

Replies have been disabled for this discussion.