[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

C++ different to C for flushing streams?

Tomás Ó hÉilidhe

11/23/2008 3:33:00 PM


In C, when you use "printf" to write to the screen, you can't be sure
that the text will actually appear on the screen unless:
1) The string being printed ends with a '\n'
or:
2) You call fflush(stdout) afterwards

How do things work in C++? If I do:

cout << "monkey\n";

, will this definitely get printed to the screen? Or do I need to do:

cout << "monkey" << endl;

I've heard that "endl" is a combination of '\n' and flush, i.e.:

cout << "monkey" << '\n' << flush;

What puzzles me though, is why someone would say that endl is a
combination of '\n' and flush if you don't need to flush the output
stream after '\n'. If you don't need to flush the output stream after
'\n', then endl would simply be equal to:

cout << "monkey" << '\n';

On a website for an IBM C++ compiler, it says that using '\n' is more
efficient than using endl because endl does a flush afterwards.
However I don't see how they could be any different if '\n' results in
an automatic flush.

Please enlighten me :-D
3 Answers

Juha Nieminen

11/23/2008 4:22:00 PM

0

Tomás Ó hÉilidhe wrote:
> In C, when you use "printf" to write to the screen, you can't be sure
> that the text will actually appear on the screen unless:
> 1) The string being printed ends with a '\n'

Are you sure the C standard guarantees that? Because, as far as I
know, the C++ standard doesn't, and the C parts of C++ are based on the
C standard.

Some C compilers might always flush stdout when a "\n" is printed, but
that's different from the C standard guaranteeing it.

> cout << "monkey\n";
>
> , will this definitely get printed to the screen?

As far as I know, there's no guarantee.

> Or do I need to do:
>
> cout << "monkey" << endl;

That will always flush.

> What puzzles me though, is why someone would say that endl is a
> combination of '\n' and flush if you don't need to flush the output
> stream after '\n'.

Because if you want to flush the stream, '\n' is not enough for that.
(It *might* be enough in the case of std::cout with *some* compilers,
but with file streams it's definitely not the case.)

> On a website for an IBM C++ compiler, it says that using '\n' is more
> efficient than using endl because endl does a flush afterwards.
> However I don't see how they could be any different if '\n' results in
> an automatic flush.

Because '\n' does not necessarily cause a flush.

Erik Wikström

11/23/2008 5:11:00 PM

0

On 2008-11-23 16:33, Tomás � h�ilidhe wrote:
> In C, when you use "printf" to write to the screen, you can't be sure
> that the text will actually appear on the screen unless:
> 1) The string being printed ends with a '\n'
> or:
> 2) You call fflush(stdout) afterwards
>
> How do things work in C++? If I do:
>
> cout << "monkey\n";
>
> , will this definitely get printed to the screen? Or do I need to do:
>
> cout << "monkey" << endl;
>
> I've heard that "endl" is a combination of '\n' and flush, i.e.:
>
> cout << "monkey" << '\n' << flush;
>
> What puzzles me though, is why someone would say that endl is a
> combination of '\n' and flush if you don't need to flush the output
> stream after '\n'. If you don't need to flush the output stream after
> '\n', then endl would simply be equal to:
>
> cout << "monkey" << '\n';
>
> On a website for an IBM C++ compiler, it says that using '\n' is more
> efficient than using endl because endl does a flush afterwards.
> However I don't see how they could be any different if '\n' results in
> an automatic flush.

Simple, "\n" does not flush the stream, it just adds an EOL character to
the stream. If you want to flush the stream you have to do so
explicitly. And since you usually wants to flush the stream after the
end of a line C++ provides the convenient "endl", which adds "\n" and
then flushes the stream.

--
Erik Wikström

James Kanze

11/24/2008 9:43:00 AM

0

On Nov 23, 5:22 pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> Tomás Ó hÉilidhe wrote:
> > In C, when you use "printf" to write to the screen, you can't be sure
> > that the text will actually appear on the screen unless:
> > 1) The string being printed ends with a '\n'

> Are you sure the C standard guarantees that? Because, as far
> as I know, the C++ standard doesn't, and the C parts of C++
> are based on the C standard.

It's a bit more complicated. The C standard defines three types
of buffering for FILE* based streams: unbuffered, line buffered
and fully buffered. When the C++ maps the iostream stuff to
FILE* stuff, it never uses the line buffered mode, so there is
no line buffering in C++. On the other hand, C++ introduces
some other ways of handling the issue (depending on why you want
line buffering):

-- At the istream/ostream level (as opposed to streambuf, where
the buffering actually occurs), there is a unitbuf flag (one
of the fmtflags defined in ios_base); if it is set, the
destructor of ostream::sentry will flush the stream, so you
effectively get a flush for every << operator.
(Interestingly enough, this is also what some pre-standard
FILE* did if buffering was disabled; functions like printf
would install a local buffer, and flush it when they were
finished.)

-- You can use std::endl to terminate lines, instead of '\n',
which effectively makes all streams line buffered. This is
preferred unless the profiler says otherwise (although if
you're outputting a series of lines with no intervening
calculating, you might want to use '\n' for all but the last
line break).

-- You can tie an output stream to an input stream. This will
cause the output stream to be flushed anytime you input from
the input stream.

One of these three features will generally provide what is
desired, often better than line buffering.

Finally, in C, on start-up, "the standard error stream is not
fully buffered; the standard input and standard output streams
are fully buffered if and only if the stream can be determined
not to refer to an interactive device." In C++, cout is tied to
cin, and cerr is initialized with unitbuf set. In both cases,
you can change this (in the case of FILE*, only before the first
IO on the stream). C++ does not behave differently depending on
whether the device is interactive, however, and neither standard
provides a means of determining whether a device is interactive.
(Under Unix, you can do "isatty( 1 )" to determine whether a
device is interactive; for files you open yourself, whether the
name matches the regular expression "^/dev/.*tty" is probably a
close enough approximation. It's possible that the first will
also work under Windows, but the second certainly not.)

Note too that in both cases, these streams are opened in text
mode (not binary). In C++, there is no provision for changing
this; in C, you can use freopen with a null pointer for the file
name; it is, however, "implementation defined which changes of
mode are permitted (if any), and under what circumstances."
(From a QoI point of view, I would expect changing to binary
mode to work on the usual systems, at least if it is done before
any actual IO.)

And of course, the C++ standard also supports FILE*, will the
exact same semantics as in C.

> Some C compilers might always flush stdout when a "\n" is
> printed, but that's different from the C standard guaranteeing
> it.

The C standard guarantees it IF output is to an interactive
device. (What is an interactive device is implementation
defined, but the intent is, I think, pretty clear.)

> > cout << "monkey\n";

> > , will this definitely get printed to the screen?

> As far as I know, there's no guarantee.

There's certainly no guarantee, and it often won't be, at least
on the systems I use, where cout is often redirected to a file.
And if stdout is redirected to a file, printf( "monkey\n" )
won't be flushed either.

> > Or do I need to do:
>
> > cout << "monkey" << endl;
>
> That will always flush.

> > What puzzles me though, is why someone would say that endl
> > is a combination of '\n' and flush if you don't need to
> > flush the output stream after '\n'.

> Because if you want to flush the stream, '\n' is not enough
> for that. (It *might* be enough in the case of std::cout with
> *some* compilers, but with file streams it's definitely not
> the case.)

According to the standard, std::cout may not be unit buffered,
and simply outputting a '\n' is not supposed to flush the
buffer. (Of course, how a '\n' is mapped to the underlying file
system is implementation defined, and on some mainframes, the
only way to write a '\n' in a text file is to physically output
the data.)

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34