Because you just do fork but don't check the return value (for 0 to execute child code), you're forking more children than you think.
The parent also does the printf and not just the child.
And, after the first loop, the first child also does a fork so you have an unexpected grandchild.
It also acts like parent and child and both do a print.
So, you get six total prints from the loop.
And, because there is no exit call in the children, they "fall through" and execute the parent code at the bottom.
So, you get four prints from the code after the loop.
And, you should loop on wait because you fork two children but only do a single wait.
Adding some getpid and getppid calls can show what is really happening:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define PRINT(_fmt) \
printf("%d/%d " _fmt,getpid(),getppid())
int
main(void)
{
int f;
setlinebuf(stdout);
for (int i = 0; i < 2; i++) {
fork();
PRINT("hello\n");
}
wait(NULL);
PRINT("world\n");
exit(0);
}
Here is the output:
242293/2809616 hello
242293/2809616 hello
242294/242293 hello
242294/242293 hello
242295/242293 hello
242295/242293 world
242296/242294 hello
242296/242294 world
242293/2809616 world
242294/2806078 world
Here is the corrected program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define PRINT(_fmt) \
printf("%d/%d " _fmt,getpid(),getppid())
int
main(void)
{
int f;
setlinebuf(stdout);
for (int i = 0; i < 2; i++) {
if (fork() == 0) {
PRINT("hello\n");
exit(0);
}
}
while (wait(NULL) >= 0);
PRINT("world\n");
exit(0);
}
Here is the program output:
242316/242314 hello
242315/242314 hello
242314/2809616 world