1

regarding this code:

#include <stdio.h>
int main(){
    int x = 1;
    if (0 == fork()){
        int x = x + 1;
        fork();
    }
    else{
        int x = 4 * x;
        fork();
    }
    printf("%d",x);
}

Some friends of mine told me that the result should be 2244, but when I try and run it, I get 1111.

Can you please help me understand how to fork() works here, and which answer is correct?

Thanks a lot!

Fred Larson
  • 60,987
  • 18
  • 112
  • 174

1 Answers1

6

The only thing that gets printed is x in the outermost scope of the main definition. It is 1, so only “1” is printed, once by each of the four processes created.

Inside the inner blocks, int x = …; creates a new object distinct from the outer x even though they have the same name. These objects are not printed, so their values are irrelevant.

In more detail, in int x = x + 1;, the x in the initializer refers to the x being declared, so this definition attempts to use the object in its own initialization. The behavior of this is not defined by the C standard,1 so the program would be permitted by the standard to go horribly astray here. However, typical compilers implement some simplistic code here, either ignoring the initialization since it is essentially meaningless or implementing the x + 1 using whatever bits happen to be already in the memory allocated for the new x. int x = 4 * x; has the same problem.

Footnote

1 Due to C 2018 6.3.2.1 2, which says the behavior is not defined when the value is used of an uninitialized automatic object whose address is not taken.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • The reason it's "not defined" is because those random bits can be a value that can't possibly be in an int. It's easier to observe in a short because of the nature of x64, and I have managed to observe a (definitely two byte) short > 65536. – Joshua Apr 04 '22 at 21:47
  • 1
    @Joshua: No, it is not. While the C standard allows there to be extra bits in integer types, and for patterns formed with these bits to represent trap values that cause behavior not defined by the standard (usually signals in old C implementations), typical modern C implementations do not have padding bits in integer types and do not have trap representations… – Eric Postpischil Apr 04 '22 at 22:19
  • 1
    … The reason the behavior is not defined is the rule I cited: C 2018 6.3.2.1 2, which says “If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.” If you have an example of 16-bit `short` behaving with a value exceeding 65,536 in a reputable modern C implementation, then show a [mre]. – Eric Postpischil Apr 04 '22 at 22:20
  • Replication does not appear to be possible today. https://pastebin.com/3fWwY8H0 ; my claim is with this specific code the compiler would be within its rights to output 65536 as a possible output if condition3() returns true but neither condition1() nor condition2() do. – Joshua Apr 04 '22 at 23:54