They are
testing you on how variables are passed. All variables are passed by value- but with an object the reference itsellf is a value that is not changed but the thing the object points to CAN change.
So we start out with obj. When it is created, I believe that a and b are initialized to zero (should check this actually, but I am fairly certain of it). I am going to call these obj.a and obj.b
Now the call is made to f. Here, obj.a is set to zero, and obj.b is set to zero. The local array c, which I will call f_local.c, has its zeroith element set to zero. So this is f_local.c[0] = 0;
Now the call is made to g(b,c).
Both are passed by value- so b itself is not taken up, a copy of b is taken. We'll call this g_copy.b. Now for c, the reference itself, essentially a pointer, is passed by value. However, THE ARRAY ITSELF WHICH IS POINTED TO IS NOT COPIED. Thus the reference g_copy.c points to f_local.c.
Now a = 1. This is obj.a = 1
b is set to 1. This is g_copy.b = 1. This is thrown away as soon as the function returns.
Now g_copy.c (pointing to f_local.c) sets the zeroith element. This is equal to f_local.c[0] = 1.
So when it returns and prints a, b, c it prints
obj.a (set to 1)
obj.b (still at 0 never changed)
f_local.c[0] (changed in function to 1)
I apologize if my explanation is not as lucid as it might be, a better nomenclature for passed values would help.