11

I am aware that most terminals are by default in line buffer mode. i.e. output is buffered and not directed to stdout until a new-line character is encountered.

So I would expect this to print nothing (at least before the buffer is filled up):

int main() {
    while(1) {
        printf("Haha");
        sleep(1);
    }
    return 0;
}

It indeed prints nothing for a short period of time.

If I want to print "Haha" every second, I can either printf("Haha\n") or do fflush(stdout) after printf. (I know this is not so portable, but it's a solution nonetheless)

Now I recall the very classic scanf program (with my addition to while(1) loop to prevent buffer flushing on program exit):

int main() {
    char char_in;
    while(1) {
        printf("Haha. Input sth here: ");
        scanf("%c", &char_in);
    }
    return 0;
}

Now the program prints Haha. Input sth here: (and wait for my input). It is not here if I remove the scanf statement. Why is that so?

Thanks.

Chung Lun Yuen
  • 319
  • 3
  • 14
  • 1
    Can you show the overall output please. – Lord Salforis Sep 15 '16 at 04:43
  • 2
    `fflush(stdout)` is fine and portable; it is [Using `fflush(stdin)`](http://stackoverflow.com/questions/2979209/using-fflushstdin) that is problematic. – Jonathan Leffler Sep 15 '16 at 04:51
  • 4
    When `scanf()` is reading from an interactive device, it often runs `fflush(stdout)` automatically if the standard output is also going to an interactive device (think 'terminal' for 'interactive device'). It is neither required nor prohibited by the standard — but the synchronization is common and has ample historical precedent. —— I do believe this has been asked (and answered) before. Now to go find the duplicate...an exercise in exasperation, probably. (Also, you'd do better with `scanf(" %c", &char_in)` on two counts — passing a pointer, and skipping white space like prior newlines). – Jonathan Leffler Sep 15 '16 at 04:53
  • @LordSalforis I've added some. Not much though. Tell me if you want to add sth more specific. – Chung Lun Yuen Sep 15 '16 at 05:10
  • @JonathanLeffler Thanks! I just skimmed through [this community wiki](http://stackoverflow.com/questions/35178520/how-to-read-parse-input-in-c-the-faq) and didn't look carefully enough. Thanks for your reminder and the answer too : ) – Chung Lun Yuen Sep 15 '16 at 05:12
  • See [`printf()` before `scanf()` issue](http://stackoverflow.com/questions/16877264/) and [`printf()` not printing on console](http://stackoverflow.com/questions/13035075/printf-not-printing-on-console) for example other questions. I'm not entirely sure either is an exact duplicate, but they're very closely related (to this and to each other). – Jonathan Leffler Sep 15 '16 at 05:46
  • Hmm ... could this behavior be protected by the as-if rule? It has to say something about the sequencing of (visible) side effects, and this is one. Normally the rule is cited regarding the compiler and it's optimisations, but shouldn't it also apply to the implementation of the standard library? – Daniel Jour Sep 15 '16 at 05:55
  • 1
    What do you mean by `...prevent buffer flushing on program exit`? – 4386427 Sep 15 '16 at 06:47
  • @4286427 when program exits, stdout is flushed and the buffer gets printed. This obscures my problem here. – Chung Lun Yuen Sep 15 '16 at 07:14

1 Answers1

5

Now the program prints Haha. Input sth here: (and wait for my input). It is not here if I remove the scanf statement. Why is that so?

Because the standard (N1570 .. "almost C11") says so, §5.1.2.3/6 (emphasis mine):

The least requirements on a conforming implementation are:

[..]

  • The input and output dynamics of interactive devices shall take place as specified in 7.21.3. The intent of these requirements is that unbuffered or line-buffered output appear as soon as possible, to ensure that prompting messages actually appear prior to a program waiting for input.

[..]

Even though your output does not contain a newline and is send to a line buffered stdout, it has to appear before your program is allowed to wait for input. This is because stdout and stdin are connected to a terminal and thus are (Attention: This is implementation defined!) what the standard calls "interactive devices".

Daniel Jour
  • 15,219
  • 2
  • 27
  • 57
  • omg. You really look into the standard documents! Thanks for your effort. Newbies like me won't know where to look otherwise. – Chung Lun Yuen Sep 15 '16 at 08:08