0
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
        fork();
        printf("Hello");
        fork();
        return 0;
}

Here the code prints Hello without using '\n' Output : HelloHelloHelloHello

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
        fork();
        printf("Hello\n");
        fork();
        return 0;
}

Here the code prints Hello with \n Output:

Hello
Hello
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    Please don't tag c questions with c++, they're different languages. – cigien Sep 27 '20 at 12:59
  • I suspect that stdio buffers up to a newline, so that both times the printf is called it puts a Hello in its buffer, that buffer is duplicated in the next fork, then upon exit(), all four processes dump their copy of that buffer. In the second, the buffer is flushed before the second fork() and is empty when the four processes exit. – stolenmoment Sep 27 '20 at 13:17
  • This code won't compile, `main` function must return an int (i.e. 0) – ThunderWiring Sep 27 '20 at 13:24
  • 1
    As a rule of thumb any call to `fork` should be preceded by a call to [fflush(3)](https://man7.org/linux/man-pages/man3/fflush.3.html) on Linux – Basile Starynkevitch Sep 27 '20 at 14:34
  • 1
    @ThunderWiring: in one of the less felicitous decisions in C99 ([§5.1.2.2.3 Program termination](http://port70.net/~nsz/c/c11/n1570.html#5.1.2.2.3) in C11), you are allowed to omit the `return 0;` at the end of `main()` — and only `main()` — and zero will be returned. It was introduced largely for compatibilty with C++98 which also allows it. I regard that rule as an abomination, but it _is_ part of the standard. Personally, I aim to always write the `return 0;` or equivalent at the end of `main()` — it's only an accident when I omit it, to be fixed ASAP. – Jonathan Leffler Sep 27 '20 at 15:51
  • The most "multi-version" compatible way to return from main is `return EXIT_SUCCESS` which almost always collapses to `return 0` except on systems where success isn't zero. I don't know which systems have success not being 0; but, it's there for portability reasons. To find EXIT_SUCCESS in your enviornment, you should add `#include ` – Edwin Buck Sep 27 '20 at 16:04
  • @EdwinBuck: Actually, the C standard says 0 has the same effect as EXIT_SUCCESS, which (I believe) caused angst for VMS where an exit code of 0 meant failure. Exiting with a non-zero status might be a portability issue; for that there is `EXIT_FAILURE` in ``. But an exit status of 0 is required to be reported to the environment as success (see C11 [§7.22.4.4 The exit function ¶5](http://port70.net/~nsz/c/c11/n1570.html#7.22.4.4p5)). – Jonathan Leffler Sep 27 '20 at 16:19
  • @JonathanLeffler Glad to see they fixed it in 2011. Of course, the actual shell return value is now implementation defined (for portability). – Edwin Buck Sep 27 '20 at 16:28

1 Answers1

4

@Stolenmoments suspicions are correct.

Basically, the first printf statements fill the stdin buffer with some data, and the second fork duplicates the stdin buffers. When all programs exit, they all flush their buffers.

To see that the granchild forks aren't printing, we can extend your program like so:

#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
        int childpid = fork();
        printf("%s %d, ", "Hello", childpid);
        childpid = fork();
        return 0;
}

and we get the output Hello 11221, Hello 0, Hello 11221, Hello 0, Clearly the childpids of the second fork are not the same, or they wouldn't be forked processes.

But as soon as we add in a fflush

#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
        fork();
        printf("Hello");
        fflush(stdout);
        fork();
        return 0;
}

we get the get the expected output HelloHello

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138