this question was on last year's exam and i have never seen anything like this in my life. I know what fork does, what it returns, but this... i can't even compile this
what is displayed when running the C code below? How many processes appeared in total (including the initial process)? Sketch the tree of these processes, indicating next to each process that displayed something the displayed value (in parentheses) Justify the answers.
int x=0;
for(fork();!fork();exit(x))
for(!fork();exit(x);fork())
for(exit(x);fork();!fork());
printf("%d\n",++x);
The answer to the headline question — are you allowed to have
fork()as aforcondition? — is "yes" because it is a function that returns anint.The answer to the unasked question — are you allowed to have
exit(x)as aforcondition? — is unclear, but using the standard C header<stdlib.h>to declareexit()means that the answer is "no" becauseexit()does not return at all, and is declared not to return a value (nominally, it returnsvoid).The code shown doesn't list the headers included. If it includes
<stdlib.h>to declare the standard C functionexit(), the code won't compile. If it doesn't include the header<stdlib.h>, the code can only be compiled without warnings under C89/C90 rules where undeclared functions are assumed to return anintvalue.Nomenclature: For the purposes of this answer, the three components of the
forloop condition areexpression-1,expression-2andexpression-3. The initial process is designated P0 — child processes are designated P1, P2, …So, working under the assumption that
exit()andfork()are both inferred to returnint(andprintf()likewise, though using a varargs function likeprintf()without a function prototype in scope leads to undefined behaviour), and thatexit()behaves like the standard Cexit()and terminates the process, and thatfork()creates a new process, returning zero in the child process and non-zero in the parent process, we can make multiple observations.1, but that is only printed if any of the myriad processes executes theprintf().for(!fork();exit(x);fork())— the!operator is irrelevant; the value returned by thatfork()is never examined.for(exit(x);fork();!fork())— the!operator is irrelevant.expression-1which results in two processes running, P0 and P1. Both processes run the first loop'sexpression-2, forking again, so there are now 4 processes, P0, P1, P2 (child of P0) and P3 (child of P1).!fork()is 1 so it executes the loop body and similarly for P3; for processes P0 and P1, the result of!fork()is 0 so the loop terminates; each of P0 and P1 executes theprintf()statement and exits.expression-3will be evaluated and the process will exit without printing anything. Note that it is a big"if"!expression-1creates a new process P4.expression-3are not executed, so further analysis of loop 3 is unnecessary.So, there were a total of 6 processes — P0..P5 (P5 being the child of P3).
The output is two lines containing
1— probably. The interleaving of the results is not determinate. There will be two1's and two newlines in the output; the first character will be a1; the last character will be a newline. In theory, the middle two characters could appear in either order, but two neat lines is the most likely output.Consider the code below code, which is a minor variant of the original. However, it compiles cleanly under C11, C18, etc without complaints from Clang (
Apple clang version 15.0.0 (clang-1500.1.0.2.5)) set fussy:The code should compile without warnings using these options.
The dance with
#undef exitundoes any macro definition ofexit()but leaves the function declaration in place. The functionterminate()is defined to return an integer value, but calls the real functionexit()which terminates the process before the return occurs. The#define exit(x) terminate(x)means that the calls toexit()in themain()function actually callterminate()instead, but the result is the same as ifexit()were called except that it ensures no undefined behaviour.The
notification()function is a simple function called when a process exits normally — it identifies which process is exiting, giving a way to check on the number of processes created by the program.I've added an appropriate top and tail for function
main()and calledatexit(notification);to get notified when processes exit. I removed the irrelevant!operators from the second and third loop controls —clangcomplained that the expression result was unused.One example run produced:
This confirms that 6 processes were created and two lines containing
1were printed, as stated in the deconstruction of the code.This is a bad exam question because you have to make a number of questionable assumptions to come up with the answer that the exam-setter expects.