Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does flushing work between C and C++ streams when they are synchronized?

By default, C++ streams (cin, cout) are synchronized with C streams (stdin, stdout). This allows mixing C and C++ style I/O. I am trying to understand what this means in practice regarding flushing. Consider the following programs:

#include <cstdio>
#include <iostream>
#include <thread>


int main() {
    printf("Hello");
    std::cout << std::flush;
    std::this_thread::sleep_for(std::chrono::seconds(2));

    return 0;
}

and

#include <cstdio>
#include <iostream>
#include <thread>


int main() {
    std::cout << "Hello";
    fflush(stdout);
    std::this_thread::sleep_for(std::chrono::seconds(2));

    return 0;
}

In both cases, output appears immediately, even though I thought cout << flush should only flush cout and fflush(stdout) should only flush printf. Why does std::cout << flush flush printf output and why does fflush(stdout) flush std::cout output?

like image 407
Ranko Avatar asked Nov 14 '25 15:11

Ranko


1 Answers

std::cout has a stream buffer that behaves like a std::filebuf over stdout ([iostream.objects.overview]). Similarly, the other streams have a buffer that acts like a std::filebuf or std::wfilebuf over stdout/stdin/stderr.

std::cout << std::flush; calls std::flush(std::cout);. std::flush(std::cout) calls std::cout.flush(). std::cout.flush() calls std::cout.rdbuf()->pubsync() ([ostream.unformatted]).

.rdbuf() is a std::streambuf object that behaves like a std::filebuf. ->pubsync() just calls the most derived ->sync(), which for std::filebuf will write any buffered characters (which there won't be if the streams are synced) then calls fflush(file) on the held std::FILE* file ([filebuf.virtuals]).

So std::cout << std::flush; will have the same effect as std::fflush(stdout), since the stream buffer for std::cout just defers to a held std::FILE* that is stdout.

Note that when the standard streams are synchronised, their stream buffer will not actually buffer any characters. Any write std::cout.put(c) will immediately call std::fputc(stdout, c) ([ios.members.static]), so if you flush using the C api the characters will already have been written to the C streams.

like image 76
Artyer Avatar answered Nov 17 '25 09:11

Artyer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!