Clarification on stdin and cin

Hey everyone,

So I'm looking for some clarification and to clear up some confusion I have in relation to cin/cout and stdin/stdout. The emphasis will be on Linux as I'm using a Ubuntu (Debian) machine but I would also like to know about how Windows deals with this too.

Recently I learned that when opening up a terminal (which is a process) the stdout and stdin will be set to tty (terminal). When I run a c++ program such as ./myProgram , myProgram will have stdin and stdout set as tty but if we specify redirection such as cat "hello.txt" | myProgram (assuming myProgram handles piped input corectly) well then stdin of myProgram will be set to stdout of cat "hello.txt".

As mentioned stdout and stdin are by default set to the terminal and have file descriptor 1 and 0 respectively. But I have a couple of questions when it comes to stdout stdin and cin and cout.

- Do C and C++ use separate/independent streams?

- If so, do C++ streams such as cin and cout work differently than stdin and stdout?

- Why does stdin read from the keyboard by default?

- To further elaborate on the above question, is stdin connected to a device driver to receive input from the keyboard?

- In Linux, C program and a C++ program; when I type from the keyboard, do the keystrokes go directly to that processes stdin? (I think in C++ the input could be buffered?)

- Why and how does C++ use streams, does cin and cout reserve space in memory(buffer) for input from the keyboard and how does the keystrokes know how to go to cin rather than stdin?

Thanks
Last edited on
It is the operating system that provides those streams. On *nixen they are labeled with file descriptors 0 and 1 (and 2 for standard error).

C and C++ don't care about the way things actually work in the OS. They each model an interface to them. C uses the fgets(), fprintf(), etc kind of stuff. C++ uses the iostream stuff. Hidden behind the scenes (in the case of C on *nixen, it is pretty direct, else it is a little more involved and/or convoluted) they both use the OS facilities to access those streams (or equivalent).

Keep in mind that "stream" here is a term meaning a byte source or a byte sink — something you get bytes from or something you send bytes to.

So:

- Do C and C++ use separate/independent streams?
They use different abstractions to access those streams. By default C++'s abstraction is linked to C's abstraction. You can disassociate them if you wish.

- If so, do C++ streams such as cin and cout work differently than stdin and stdout?
In the abstraction, yes. Once the data gets to the OS's end of things, though, no.

- Why does stdin read from the keyboard by default?
Because that is how the OS does it by default.

- To further elaborate on the above question, is stdin connected to a device driver to receive input from the keyboard?
Yes.*
*Unless it has been redirected from a different stream source.

- In Linux, C program and a C++ program; when I type from the keyboard, do the keystrokes go directly to that processes stdin? (I think in C++ the input could be buffered?)
No. It would be sweet if they did, but they are first pretty heavily processed. There are actually really good reasons for this, and it is much more complicated than you'd think, but it is what it is. If it helps to understand this, remember that the keyboard is not a simple byte source, but a fairly complicated device that needs special OS code to communicate with; not all keyboards work the same.

- Why and how does C++ use streams, does cin and cout reserve space in memory(buffer) for input from the keyboard and how does the keystrokes know how to go to cin rather than stdin?
"Streams" here is a C++ term for a class of object for accessing an abstraction over byte sources and byte sinks.

Again, the bytes don't "go to" anything. The abstraction (cin, stdin, etc) simply provides the programmer a way to access the byte streams and nominally process them for our programming needs.

Consequently, you can freely mix fgets() and cin>> in your code.*
*Assuming you don't do something to confuse their ideas of what the input state is.


The ideas behind redirectable streams were fundamental to the design of Unix, and a revolutionary idea. It was widely copied by other OSes as well, including CP/M, which was DOS's direct ancestor (of sorts), which is Windows' ancestor. What it meant was that you can get data from any source, and even swap sources, and your program can still use it. Likewise, your program can output data that can be directed to any sink you desire without the program's needing to be any the wiser.

It is worth your time to pick up a book on the design and implementation of the Unix system. The top two in your google search are the droids you are looking for:
https://www.amazon.com/Design-Implementation-Unix-Operating-System/dp/0201546299
https://www.wiley.com/en-us/UNIX+Filesystems:+Evolution,+Design,+and+Implementation-p-9780471164838

It is also worth looking at how C++ streams work. Take a look through the basic_streambuf (https://en.cppreference.com/w/cpp/io/basic_streambuf) for implementation details. It boils down to how the underflow and overflow virtual functions are implemented.

The special streams cin, cout, and cerr (and clog) are special, implementation-defined black boxes, because making them work is again a bit more involved than you would think at first blush.

Hope this helps.
Last edited on
Your impression seems to be that your software is doing way more than it actually is. Most of the work is done by the rest of the software in the stack.

- Why does stdin read from the keyboard by default?

Standard input is just a file. Stuff is written to it by arbitrary software, and your program reads it at its discretion.

The kernel monitors the keyboard. The kernel makes the state of the keyboard accessible via character special files in /dev/input/. User-space software can monitor those files to figure out what keys are being pressed. By some means (perhaps via the X server acting as a broker), the terminal learns what the user has typed. At the terminal's discretion it writes the contents of the current line into the current process's stdin, which is just a file.

With regards to redirection, it's the terminal that sets it up, and the kernel that makes it happen, see man 2 dup.

The special streams cin, cout, and cerr (and clog) are special

Not that special, they're initialized by means of an idiom presumably invented by Jerry Schwarz, who was partially responsible for <iostream>'s design.
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter
Last edited on
The nifty counter has nothing to do with how they function.
(It is pretty cool, though. I've used it myself.)
The nifty counter has nothing to do with how they function.

Okay, I agree.

I don't know what's special about those streams. Will you humor my laziness and tell me what to research on my own?
Heh, sorry, you've got to dig deep into getting them set up properly on Windows. You're playing with *nix, and they are a pretty simple operation there. Windows carries a lot of baggage. I wish I could tell you more, but it has been a while since I've gone deep sea fishing for this kind of stuff. Nothing like reading source code and random nonsense on the internet.

The reason is that Windows doesn't have normal stdin and stdout file descriptors, so everything you see is at some level an abstraction over what does exist, particularly as it relates to console subsystem processes.

All this is handled by the implementation/library deep behind the scenes. I recommend you look through the Windows LLVM/Clang sources to see what they connect to in the MS Kits there — that version of Clang works properly on Windows.
The reason is that Windows doesn't have normal stdin and stdout file descriptors, so everything you see is at some level an abstraction over what does exist, particularly as it relates to console subsystem processes.

This was enough to jog my memory, thanks. There is a component called conhost that is related.

This article (series) gives a nice overview of the implementation
https://devblogs.microsoft.com/commandline/windows-command-line-inside-the-windows-console/

It contains this ludicrous gem:
3rd party Consoles have to launch a Command-Line app off-screen at, for example, (-32000,-32000). They then have to send keystrokes to the off-screen Console, and screen-scrape the off-screen Console’s text contents and re-draw them on their own UI! [...]

The new Windows Terminal is supposed to solve a lot of these problems.
I installed it but haven't played with it much yet. It seems very, very nice.
At first I was a bit skeptical about Windows Terminal, the ol' Win command-line app works for me.

After reading about it at its github page I can see this app does serve a purpose.
I've played with it a little more since, and it is indeed very nice.
Thanks for the feedback, I will probably be installing it on a probationary basis, mucking around with it for a bit.
Hey guys, great information :) I haven't had a chance to fully assimilate it yet due to being swamped with college work, mainly for UML(yuck), web dev (meh) and databases.

But will reply asap :) thanks guys also @Duthomhas I added that book to my wishlist :p
Topic archived. No new replies allowed.