You are using a fork in the code which creates a child process, which executes all the lines below the fork(), hence we have two processes submitted to the scheduler in total and the sequence of execution of these two processes(parent or child) is decided by the scheduler.
Since you are not using wait() in the parent, the sequence of execution of parent and child is unpredictable. And about interleaving of outputs "AA" and "BB" is because of race conditions which may or may not happen depending on preemption.
If you run your code by including necessary header files, you'll see that sometimes there is an interleaving of outputs (BBAABB....) and sometimes there isn't (and you get BB....AA....)
So, it isn't necessary that the parent(father) process is always executed prior to the child(son).
Actually, this is what is supposed to happen and I got these outputs when testing the code on VSCode.
But when you run your code in the terminal directly, the output is always the same i.e., without interleaving because there is no context switch. This happens due to the stdout buffer present in the VScode which does not allow the program to run directly on the terminal instead uses a pipe, and you get the output only when the buffer is fully flushed.
P.S: Try to run the same code more than once you'll get both the outputs
Code :
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(){
pid_t pid = fork();
int i;
setbuf(stdout,NULL);
if(pid == 0){
for(i = 0;i < 10;i++){
printf("AA");
}
sleep(1);
exit(0);
}
else{
for(i = 0;i < 10;i++){
printf("BB");
}
sleep(1);
}
return 0;
}