1

I have this code:

#include <stdio.h>

int main(void) {

int d=0;

d = getchar();
printf("%d\n", d);

}

Output:

^Z
-1

From what I understand there are two things that could be happening here:

  1. Getchar reads ctrl+z and it returns it.
  2. Getchar reads nothing and returns EOF.

Are there any more possibilities?, which of the two is correct?

3
  • 1
    The ^Z you see isn't an input value: it is the echo from the keyboard handler, as with other keys you press. Option 3, getchar() reads the Ctrl-Z value 26 and converts it to the EOF flag. Commented Mar 23, 2024 at 15:59
  • In this case the value is assigned to d anyway. In your previous scanf example it was not. Commented Mar 23, 2024 at 16:05
  • @WeatherVane Thank you very much! I just have one follow-up question: When I look at the ASCII table it says that 25 is "end of medium", and 26 is "substitute". Could it be that it is 25 and not 26? Commented Mar 23, 2024 at 16:22

1 Answer 1

3

There are two parts to this:

  1. What getchar() does.
  2. What the console/OS/run-time environment does.

What getchar() does is clear:

Returns EOF (-1) on any failure. If the failure is caused by end-of-file additionally sets the eof indicator (see feof() on stdin).

What the OS console does in this case (Windows):

  1. Receive input Ctrl-Z (non- printing ASCII control character 26)
  2. Echoes non-printing Ctrl-Z as ^Z
  3. Traps Ctrl-Z as EOF and inserts EOF into stdin (not Chr.26).

Noting that Ctrl-Z (SUB) is peculiar to Windows, MS-DOS and before that CP/M. In CP/M SUB was used to pad files to a multiple of 128 bytes (a requirement of its primitive filesystem), so for files that are not a multiple 128 bytes it essentially marked the end-of-file. On Unix and Linux Ctrl-D (EOT - end-of-transmission) is used which arguably makes more sense, but neither is truly an end-of-file, the terminology comes from treating stdin as a "file" stream, which simplifies device driver interfaces and redirection.

So in summary, the system (Windows) treats Ctrl-Z in the console as an instruction to insert an EOF into the console input stream, and getchar() returns EOF, and sets the input stream's EOF flag. The echoing of ^Z (or any character) is a platform specific side-effect. getchar() does not in fact echo anything.

It is not truly the end of the stream, and input can resume after calling one of rewind(), fsetpos(), fseek(), or clearerr().

Note also that this is strictly behaviour of the console input stream. If stdin were redirected from a file , EOF would be indicated at the true end-of-file, and that file could contain Ctrl-Z (SUB) characters, and these would be returned by getchar() as value 26.

Sign up to request clarification or add additional context in comments.

9 Comments

As side note, when a file is opened in text mode in Windows, a character 26 is treated as it was in the old days and the file read ends at that point.
Thank you very much! So it is Windows and not getchar that converts 26 to -1? You say "So in summary, the system (Windows) treats Ctrl-Z in the console as an instruction to insert an EOF into the console input stream", does this mean it inserts -1 into the console input stream?
@user394334 I am really saying it is "as if" the EOF were inserted into the steam. The exact underlying implementation may not do exactly that. It is a model of behaviour that suits the purpose of writing code using stdio. If you want more control at a lower level, use the Windows Console API
Last question: So after that does getchar look in the stream, and detects the EOF that Windows put into the stream, and return EOF, which now is -1(that is getchar sets it as -1?)?
I did check that before posting my comment.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.