Strange behaviour of printf. See the code below and please tell why it behaves in this way.

K

Kevin D. Quitt

No it was defined in that implementation.

"Defined in that implementation" is not a meaningful phrase. "Defined"
means it comes from the Standard. And even by your definition you can't say
it was defined in the implementation, the observed behaviour might be
entirely an accident. The code's behaviour is undefined, by definition.
 
K

Keith Thompson

SM Ryan said:
No it was defined in that implementation. Once you have some real
world experience, you will discover argument list and argument
passing are always meticulously well defined in each
implementation. This allows linkages between the code of one
compiler and another--an important real world consideration. Often
the argument passing is not even left up the compiler: the CPU
designer defines external linkage protocols and all compilers for
that CPU. Internal linkages, in C that would mean calling a static
function, can follow alternate protocols but often don't except for
optimising compilers.

[ Obnoxious '#' quoting character changed to '>'. ]
[ Obnoxious long lines re-wrapped. ]

(Context: the code in question passed a struct { int i; int j; } to
printf with a format string specifying two int arguments; it happened
to print the i and j members of the struct.)

First, what we discuss here is standard C. We recognize that
implementations have system-specific characteristics, but if we're
going to discuss non-portable code we will *at least* point out that
it's non-portable, and why it's non-portable. The code in question
invokes undefined behavior, and will almost certainly break on some
implementations. The task the code was trying to accomplish could
easily be achieved portably; even if it's a hack rather than a bug,
there's no advantage in using it. It's also an extremely fragile
technique. It might work for printf() but fail for a function that
doesn't take a fixed number of arguments, or, as you point out, it
might work for an external function but fail for a static function.
Imagine a program's behavior changing subtly because you add a
"static" keyword to a function definition. Imagine tracking down the
bug, assuming you even notice it. Now imagine avoiding such bugs by
writing portable code in the first place.

Second, "defined" means "documented". If you can cite the
system-specific documentation that states, or implies, that the code
is guaranteed to behave in the observed manner you *might* have a
point. The OP was using VC++. Was your statement based on the actual
VC++ documentation, or were you guessing? I can't tell, because you
didn't provide any hints as to *why* the OP's code was equivalent to

printf("i==%d i==%d \n",var.i,var.j,var.i);

You could have mentioned that excess arguments to printf() are ignored
(the standard actually specifies that). But most importantly, if you
intended to provide information that's specific to VC++, you should
have said so. This is comp.lang.c; unqualified statements made here
are assumed to refer to the standard language. In that context, your
answer was simply wrong. This isn't even about redirecting the
discussion to a system-specific newsgroup; it's about making
statements that are misleading in the context of this one.

Just providing a literal answer to a poster's question is often not
helpful, as you've demonstrated. Your answer may (or may not) be
correct within the narrow confines of the OP's particular
implementation, but it could easily lead the OP to believe things that
simply aren't true. And now you're annoyed at the rest of us for
providing useful information rather than just providing a "correct"
but misleading answer to the question.
 
P

Peter Shaggy Haywood

Groovy hepcat Markus Moll was jivin' on Tue, 17 May 2005 14:19:35
+0200 in comp.lang.c.
Re: Strange behaviour of printf. See the code below and please tell
why it behaves in this way.'s a cool scene! Dig it!
VC++ ought to reject this code, as it is not valid C++. However, you're
asking in a C group about C code, so I assume you really want to compile
this as a C program. Then the compiler should warn for several reasons.

Nonsense! The code is legal (C90), as far as the compiler knows,
notwithstanding the non-portable return value of main(). The error is
in the use of a library function, not the syntactical correctness of
the code.
Firstly, as far as I know, implicit int declaration is discouraged even in

True. It is discouraged, but legal in C90. Had he a C99
implementation, he would have recieved a diagnostic, as this is
illegal in C99.
C. Secondly, the compiler will notice that the arguments of printf don't
match the format string.

No, the compiler will do no such thing. Some compilers do. The one
the OP is using doesn't. They are not required to do so. This is
simply a case of undefined behaviour. Anything may happen, including
diagnosing the arguments passed to printf() or simply ignoring them
and quietly passing them.
This is also the reason for the observed
behaviour.
You're supplying a struct test, then an int. printf expects two ints.
Now accidentally your struct test is nothing but two ints (i and j).

Possibly. Probably. But even this is not guaranteed. Structures may
contain padding, so the output the OP could have got may be quite
different. The padding may even have formed a trap representation when
treated as an int (though that wouldn't happen with the implementation
he's using). Again anything may happen. There is no right or wrong
behaviour for cases like this.
These are printed.

GCC says:
7: warning: return type defaults to `int'
In function `main':
12: warning: int format, test arg (arg 2)

Yes, gcc catches this. VC++ does not.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 
S

SM Ryan

# First, what we discuss

Do you always use the royal plural? You aren't speaking for me.
Nor are you speaking on behalf of the nonexistent newsgroup moderator.

# implementations. The task the code was trying to accomplish could
# easily be achieved portably; even if it's a hack rather than a bug,

The code had no task. It was a result the original poster didn't
understand but anybody with compiler writing experience can understand.

# "static" keyword to a function definition. Imagine tracking down the
# bug, assuming you even notice it. Now imagine avoiding such bugs by
# writing portable code in the first place.

You're in self-righteous lather over nothing. Nobody has said passing
a struct by value where individual ints are expected is good idea.

Still doesn't mean you can't understand what happens when then happens.

# point. The OP was using VC++. Was your statement based on the actual
# VC++ documentation, or were you guessing? I can't tell, because you
# didn't provide any hints as to *why* the OP's code was equivalent to
#
# printf("i==%d i==%d \n",var.i,var.j,var.i);

Because callee doesn't know the argument list length, it needs the first
argument location and computes later arguments from that. Nearly all CPUs
push arguments back to front on a stack that decrements on push; the final
stack pointer points at or near the first argument with successive
arguments at increasing stack addresses. Because the struct needs no
padding and fields are at ascending addresses, pushing the struct is
the same as push the arguments in reverse order.

Loading the top few words of the argument list in registers
doesn't substantially change this.

A less popular way today is to allocate the argument vector elsewhere in own,
loc, or heap storage, fill it in, and pass in the argument vector address
in. For interoperability and simplicity, such argument vectors are laid
out in ascending address for successive arguments. The struct in such
a vector would be the same as two successive ints.

What would cause problems is a machine that pushes back to front with
a stack that increments on push. But such machines are rare today.

# (the standard actually specifies that). But most importantly, if you
# intended to provide information that's specific to VC++, you should

It's not specific to VC++ or gcc or Fortran or Pascal. It's based on
experience with the kinds of machines that are actually in use today.
If you don't have that much experience, would you even understand the
explanation?

# the rest of us for

Stop using the royal plural. Speak for yourself. Let others speak
for themselves.

I have my own opinions on passing structs, but since those weren't
asked for, why present them?
 
E

E. Robert Tisdale

SM said:
> cat main.c
#include<stdio.h>

typedef struct test{
int i;
int j;
} test;

int main(int argc, char* argv[]) {
test var = {10, 20};
int k = 33;

printf("i = %d\ti = %d\n", var, k);
return 1;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
main.c: In function `main':
main.c:12: warning: int format, test arg (arg 2)
i = 10 i = 20
When you pass a struct by value, all the fields of the struct
are placed in the argument list in order, along with any padding.

Bingo!
 
K

Keith Thompson

E. Robert Tisdale said:
SM Ryan wrote: [snip]
When you pass a struct by value, all the fields of the struct
are placed in the argument list in order, along with any padding.

Bingo!

If ERT means to imply that this is implied by the language definition,
he is mistaken.
 
S

S.Tobias

Do you always use the royal plural? You aren't speaking for me.

Are you being rude, or really so stupid? Keith is speaking for me,
and for those that don't answer you, because they have killfiled you.
Nor are you speaking on behalf of the nonexistent newsgroup moderator.

At present he's on leave (or something). If he were here, you would
have been called an vqvbg and moderated out of here long ago.

[Why isn't Dan Pop helpful anymore? I think I've seen his posts this year.]

[snip]

I'm not going to comment on any of your insane arguments (Keith
has said enough anyway). If you can't understand the difference
between a "guaranteed behaviour" and a "coincidence" then your
place is in the audience.
 
S

SM Ryan

#
# > > First, what we discuss
#
# > Do you always use the royal plural? You aren't speaking for me.
#
# Are you being rude, or really so stupid? Keith is speaking for me,

Are you being dense or really obnoxious? comp.lang.c is not a moderated newsgroup.
He can speak for his clique if he has verified they all agree with him. As to
assuming he speaks for everyone--programmers are supposed to know about the
dangers of hidden assumptions.

# At present he's on leave (or something). If he were here, you would
# have been called an vqvbg and moderated out of here long ago.

There is no moderator. Live with it. You're free to restrict your browsing
to comp.lang.c.moderated.

For the last 15 years comp.lang.c has decayed from a useful newsgroup
to a nasty little clique that is perfectly willing to engage in off topic
soliquies amongst themselves but goes ballistic whenever a lost newcomer
strays in with a real question. And most of the off topic rants are premature
kneejerk responses which betray the clique's agenda: any reference to a POSIX
function which is not ANS C is automatically ranted even with the issue is
not the semantics of function but the syntax of the call and surrounding code.


# I'm not going to comment on any of your insane arguments (Keith
# has said enough anyway). If you can't understand the difference
# between a "guaranteed behaviour" and a "coincidence" then your
# place is in the audience.

Don't lecture your betters.
 
S

S.Tobias

Are you being dense

Dense? I'm trying to give you a hint. Two is not enough for "we"
for you? Fine. Google for: "group:comp.lang.c what we discuss".
Not enough yet?
or really obnoxious?

What did I say "obnoxious" last time?
comp.lang.c is not a moderated newsgroup.

So what? Do you piss in the park? Do you fart at dinner? Do you
whistle in the church? Need more hints?
He can speak for his clique

Clique??? Who? Where?
if he has verified they all agree with him.

I'm sure Keith knows what he is saying.

There is no moderator. Live with it. You're free to restrict your browsing
to comp.lang.c.moderated.
Yesss...


For the last 15 years comp.lang.c has decayed from a useful newsgroup
to a nasty little clique that is perfectly willing to engage in off topic
soliquies amongst themselves but goes ballistic whenever a lost newcomer
strays in with a real question. And most of the off topic rants are premature
kneejerk responses which betray the clique's agenda: any reference to a POSIX
function which is not ANS C is automatically ranted even with the issue is
not the semantics of function but the syntax of the call and surrounding code.

Yeah, yeah... and they're after your dog, too, you know... <sip>...
those bandits don't even allow you to have l337 quotation characters,
either <sip>... too bad... ya know... right... <sip>... life is
darn tough... really darn tough... Let's have another pint...

Don't lecture your betters.

I have enough brains to know whom not to listen to. Especially
not to those "betters" that teach their betters.
 
C

CBFalconer

S.Tobias said:
.... snip ...


I have enough brains to know whom not to listen to. Especially
not to those "betters" that teach their betters.

I think the time for this has come:

+-------------------+ .:\:\:/:/:.
| PLEASE DO NOT | :.:\:\:/:/:.:
| FEED THE TROLLS | :=.' - - '.=:
| | '=(\ 9 9 /)='
| Thank you, | ( (_) )
| Management | /`-vvv-'\
+-------------------+ / \
| | @@@ / /|,,,,,|\ \
| | @@@ /_// /^\ \\_\
@x@@x@ | | |/ WW( ( ) )WW
\||||/ | | \| __\,,\ /,,/__
\||/ | | | jgs (______Y______)
/\/\/\/\/\/\/\/\//\/\\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
==============================================================
 
S

S.Tobias

[snip all]
| PLEASE DO NOT | :.:\:\:/:/:.:
| FEED THE TROLLS | :=.' - - '.=:

Whomever you had in mind, I am sorry I got unnerved.
I'll try to keep more quiet next time.
I'm quitting right here.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top