No, it isn't, really. It's internally buffered. Most calls to getchar do not read anything, they just return a pointer to the next character in an already read buffer.
> No, it isn't, really. It's internally buffered. Most calls to getchar do not read anything, they just return a pointer to the next character in an already read buffer.
Not only that, it's permissible for getchar() to be implemented as a macro, so you might even avoid an actual function call too.
It’s explicitly permissible for every C library function to be implemented as a macro (as well as an identically-named function in case you need the address), but they must preserve the illusion by evaluating every argument exactly once. You were probably thinking of getc(fp), which is special [and different from fgetc(fp)] in that it’s additionally allowed to evaluate fp multiple times: getchar() takes no arguments, so it doesn’t matter either way. Yes, the naming is confusing.
... In which case, getchar_unlocked() from POSIX 1993 and later is your friend, when used together with flockfile() / funlockfile(). Or, well, as much of a friend as an explicit locking function can ever be. (Over in Windows land, MSVC used to have a non-threaded static C runtime as well, which doesn’t strike me as a stupid idea for this kind of simple program, but for some reason musl on Linux doesn’t do non-threaded builds.)