understanding the output of g() function

I was doing some end of chapter question and had a problem with the following code. Could anyone help me understand the output [ g() ] of the the following snippet with the overall flow of the process. I just want the explanation of the process.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  int a;
  int b = 2;

  int f(void)
  { 
    int x = a++;
    { 
        static int a;

        a = b++;
        { 
            int b = a + x;
            x += b;
        }
    }
    return x + a + b;
  }



  void g(void)
  { 
      printf("%d", f() + f());
  }
f() + f()
Call the function f() twice, adding together what you get back from it.

printf("%d",
And then output that sum.
g is easy ;)
g outputs the result of f() + f(). f returns an integer, so you can add these as if f were simply an integer.

f is a mess.
f makes use of 2 copies of the variable a, one of which is undefined and the other is static so it keeps its value between runs.

x is undefined because it uses the undefined a.
the result of f is undefined because it uses x which is undefined because it used the undefined a.

therefore f produces random garbage. The random garbage is different every time you call f, so g prints the sum of 2 pieces of garbage, which is, of course, more garbage. b is also garbage. only the local static a which is cooked up from b is valid.

Last edited on
f makes use of 2 copies of the variable a, one of which is undefined
::a is declared at namespace scope and so has static storage duration and is therefore initialized to 0.

@OP
This question is a test of short-term memory and not much else. I wouldn't worry much if you can't trace it.
Last edited on
Some things to note:

{ } blocks are used to create an inner scope. The b variable defined at line 12 has nothing to do with the b variable defined at line 2; the former shadows the latter. The original b is referred to once again on line 16, after the inner-scope ends.

Adding "static" to a local variable keeps that variable's value set even between function calls, so you have to remember what it was set to from the last call.

As mbozzi notes, global variables are initialized as 0.

I had crap like this for the first-year programming class at my uni. It's so painful, and is almost certainly unlike anything you'll actually have to see in the real world (well, I take that back, there is some nasty code out there...)


a_outer = 0;
b_outer = 2;
f() is called
{
    x = 0; a_outer incremented to 1;
    {
        a_inner put into memory;
        a_inner = 2; b_outer is incremented to 3;
        {
            b_inner = a_inner + x = 2 + 0;
            x = x + b_inner = 0 + 2 = 2;
        }
    }
    return x + a_outer + b_outer = 2 + 1 + 3 = 6;
}

[first f() returns 6]

a_outer and b_outer are still 1, and 3, respectively
a_inner is still 2

f() is called again:
{
    x = 1; a_outer incremented to 2;
    {
        a_inner = 3; b_outer is incremented to 4;
        {
            b_inner = a_inner + x = 3 + 1 = 4;
            x = x + b_inner = 1 + 4 = 5;
        }
    }
    return x + a_outer + b_outer = 5 + 2 + 4 = 11;
}

[second f() returns 11]

f() + f() = 6 + 11 = 17



Important note: The order in which f() is called is actually unspecified. It could be calling the second f() first. But that doesn't matter in this case, because the addition here is commutative, and the side effects for both calls are commutative too. You either have 11 + 6 or 6 + 11, either way it's 17.
Last edited on
Topic archived. No new replies allowed.