Strange printfs !!

  • Thread starter karthikbalaguru
  • Start date
K

karthikbalaguru

Hi,

I get different output for some simple
set of printf statements in Visual C++
2008 express edition and gcc.

I am eager to know the reason for
the differences in the output.

#include<stdio.h>
int main(void)
{
printf("\n12");
printf("\b34");
printf("\r56");
return 0;
}

The output is 56 in Visual C++ 2008 Express Edition
The output is 564 in gcc environment
Any ideas,

Thx in advans,
Karthik Balaguru
 
K

Kojak

Le Mon, 2 Mar 2009 23:17:02 -0800 (PST),
karthikbalaguru a écrit :
#include<stdio.h>
int main(void)
{
printf("\n12");
printf("\b34");
printf("\r56");
return 0;
}

The output is 56 in Visual C++ 2008 Express Edition
The output is 564 in gcc environment

This seems to be a terminal capabilities issue. Does the test
was done on the same OS?
 
K

Kaz Kylheku

karthikbalaguru said:


At the point where you end the program, the status of the output
stream is a little odd, because you haven't ended the code with a
newline, and you haven't flushed the stream.

The behavior is undefined if the last character written to a text stream isn't
a newline, but that is irrelevant here. Visual C++ doesn't impose the
requirement, and I don't know of any ``gcc environment'' that does.

What's likely happening is a difference in terminal emulation in the console:
destructive backspace/carriage-return versus non-destructive.
A little experimentation shows that adding fflush(stdout) to the
code after the final printf results in gcc's producing 56 as output
rather than 564.

It's very surprising that a fflush(stdout) immediately before returning from
main makes any difference at all, given that the normal termination of a C
program requires all output streams (or update streams on which the most
recent operation wasn't input) to be flushed!

I'm curious in what environment a redundant stream flush just prior
to program termination makes any difference.
 
C

Christoph Conrad

Hi Kaz,

* Kaz Kylheku said:
The behavior is undefined if the last character written to a text
stream isn't a newline, but that is irrelevant here.

Undefined? In the ISO C++ standard i can't find that statement, but in
ISO C appendix "J.3 Implementation-defined behavior", "J.3.12 Library
functions":

,----
| Whether the last line of a text stream requires a terminating new-line
| character (7.19.2).
`----
It's very surprising that a fflush(stdout) immediately before
returning from main makes any difference at all, given that the normal
termination of a C program requires all output streams (or update
streams on which the most recent operation wasn't input) to be
flushed!

Yes, that difference also astonishes me.

Kind regards,
Christoph
 
M

Mark Wooding

Richard Heathfield said:
karthikbalaguru said:
#include<stdio.h>
int main(void)
{
printf("\n12");
printf("\b34");
printf("\r56");
return 0;
}
[...]
At the point where you end the program, the status of the output
stream is a little odd, because you haven't ended the code with a
newline, and you haven't flushed the stream.

Unnecessary.

5.1.2.2.3 Program termination

[#1] If the return type of the main function is a type
compatible with int, a return from the initial call to the
main function is equivalent to calling the exit function
with the value returned by the main function as its
argument;9) reaching the } that terminates the main function
returns a value of 0. If the return type is not compatible
with int, the termination status returned to the host
environment is unspecified.

7.20.4.3 The exit function

[#4] Next, all open streams with unwritten buffered data are
flushed, all open streams are closed, and all files created
by the tmpfile function are removed.

So stdout is implicitly flushed anyway.
A little experimentation shows that adding fflush(stdout) to the code
after the final printf results in gcc's producing 56 as output rather
than 564.

That's very strange. I don't see any difference between the two -- as
I'd expect.

Note that (assuming common control-character behaviour not guaranteed by
the C standard) the cursor will end up over the top of the `4'
character, which is therefore likely to be overwritten by subsequent
output. I'd say that it's much more likely that your testing
environment differed in its subsequent output behaviour between the two
executions than that adding or removing a call to fflush made a
difference.

-- [mdw]
 
C

Christoph Conrad

Hi Pete,

* pete said:
Yes, "Whether"; But if it does require a terminating new-line and a
terminating new-line isn't there, then what happens?

Mhmmmm, yes. You're right.

Kind regards,
Christoph
 
H

Hans-J. Ude

Kaz said:
I'm curious in what environment a redundant stream flush just prior
to program termination makes any difference.

I was curious too so I tried Cygwin/gcc and Linux/gcc.
Cygwin (gcc V. 3.4.4) : 564
Linux (gcc V. 4.3.2) : 56
No difference between fflush(stdout) or not in both cases. Just to make
the confusion a bit bigger :)

Hans
 
K

karthikbalaguru

I was curious too so I tried Cygwin/gcc and Linux/gcc.
Cygwin (gcc V. 3.4.4) : 564
Linux  (gcc V. 4.3.2) : 56
No difference between fflush(stdout) or not in both cases. Just to make
the confusion a bit bigger :)
Interesting !!

Finally, it boils down to two possibilities.

Does it mean that gcc V 4.3.2 has the fixes and hence
gives the correct output . But, not gcc V 3.4.4 (Older
version of gcc) ?

Or,

Does it mean that gcc based on windows environment (cygwin),
give output similar to Visual C++ 2008 Express edition, but
not the gcc of the linux OS ?

Karthik Balaguru
 
K

Kojak

Le Tue, 03 Mar 2009 15:36:50 +0100,
Hans-J. Ude a écrit :
I was curious too so I tried Cygwin/gcc and Linux/gcc.
Cygwin (gcc V. 3.4.4) : 564
Linux (gcc V. 4.3.2) : 56
No difference between fflush(stdout) or not in both cases. Just to
make the confusion a bit bigger :)

Test this :

------8<------8<------8<------8<------8<------8<------8<------8<
#include <stdio.h>
#include <stdlib.h>

int main (void)
{
printf ("\n12");
printf ("\b34");
printf ("\r56");
fflush (stdout);
system ("sleep 10");
return 0;
}
------8<------8<------8<------8<------8<------8<------8<------8<

and check the output and where the cursor is...

56 is just what I expect when I follow the sequence :

\n -> cursor at the beginning of a new line
12 -> write 12
\b -> one backspace (cursor back on 2)
34 -> write 34 (you get 134)
\r -> carriage return (move cursor at the beginning of the
same line without erasing the line,
cursor is now on '1')
56 -> write 56 and let cursor on '4'

... and so on ...

As I said, it's only a terminal issue.

Cheers,
 
K

Keith Thompson

karthikbalaguru said:
Interesting !!

Finally, it boils down to two possibilities.

Does it mean that gcc V 4.3.2 has the fixes and hence
gives the correct output . But, not gcc V 3.4.4 (Older
version of gcc) ?

Or,

Does it mean that gcc based on windows environment (cygwin),
give output similar to Visual C++ 2008 Express edition, but
not the gcc of the linux OS ?

No and, respectively, no.

Here's the program:

#include<stdio.h>
int main(void)
{
printf("\n12");
printf("\b34");
printf("\r56");
return 0;
}

First of all, the differing versions of gcc are unlikely to matter.
The output of the program depends on the runtime library, not on the
compiler; the compiler should just generate a sequence of calls to
printf. printf is part of the runtime library, not the compiler. The
behavior of printf is unlikely to change across versions of the
runtime library.

If you're seeing different output on Cygwin vs. Linux, I strongly
suspect it's because you have a different shell prompt -- and in fact
the default bash prompt on Cygwin starts with a new-line. The actual
output is probably the same in both cases; it's just being overwritten
differently. Assuming that the response to the control characters is
what's typical for both systems, here's what should happen when the
program runs:

It prints a new-line, leaving an empty line and jumping to the
next line.
It prints "12".
The cursor moves back one column (without erasing anything),
leaving it over the '2'.
It prints "34"; the '3' overwrites the '2', leaving "134".
It prints a '\r', moving the cursor to the beginning of the
line, on top of the '1'.
It prints "56". The '5' overwrites the '1', and the '6'
overwrites the '3', leaving us with "564", and the cursor on top
of the '4'.
The program terminates.

So the net result of the program is to display a blank line followed
by "564", and to leave the cursor sitting on top of the '4'. What
happens next is outside the program's control. On both Cygwin and
Linux, assuming you ran the program from the shell, the shell then
prints its prompt. On Cygwin, where the prompt begins with a
new-line, the cursor moves to the next line and (what's left of) the
program's output remains visible. On Linux, where the prompt doesn't
begin with a new-line, the prompt is written on the same line as the
end of the program's output, and the trailing '4' is clobbered.

You can get exactly the same behavior on Cygwin and Linux if you set
the prompt (in bash, "PS1=whatever") to the same value on both.

A couple more things to try (these commands are system-specific, but
will work on both Cygwin and Linux; assume the program's executable is
"./prog"):

./prog ; sleep 5
# Wait 5 seconds before printing the prompt.

./prog | cat -A
# Print control characters in a visible way; end-of-line is $,
# backspace is ^H, return is ^M.

./prog > prog.out
view prog.out
# Or use your preferred editor to examine the output.

The standard allows some freedom in what output the program will
produce. On a system where the last line of a text stream must be
terminated by a new-line, the behavior is undefined. But on the
particular systems in question, this doesn't apply; the program will
just print the specified characters to stdout. There's a difference
between the output the program produces (which is well defined on
these systems) and what appears in your terminal window. This *can*
be affected by terminal settings, but that's not what's happening in
this case (though it was a good guess). The difference is explained
by the setting of the shell prompt -- something entirely outside the
scope of C.
 
K

Kojak

Le Tue, 03 Mar 2009 17:57:14 +0000,
Richard Heathfield a écrit :
(a) if it ain't broke, don't fix it;
(b) if it's only broke a little bit and the hassle of fixing it
exceeds the cost of leaving it broken, don't fix it.

You forget µsoft rules:

(c) do not fix as long as it sells. :-D

Sorry,
 

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

Similar Threads

Strange !! 10
Use of 100; 3
It works without stdio.h !! 22
Strange - a simple assignment statement shows error in VC++ but worksin gcc ! 307
int pointers & characters !! 17
Strange behaviour of while loop !! 14
%n !! 36
++*p++ 24

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top