5.12. Answers to Exercises
- 1. If you got this one right, congratulations! It's just filled with tricks, but they're all things that you might run into in a real (although poorly written) program. Here's the answer:
- The first question is why there are only three values displayed by each output statement. The for loop that calls the Calc routine and displays the results should execute 5 times, shouldn't it?
- This is the first trick. Since i is a global variable, the statement i ++; in the Calc function affects its value. Therefore, i starts out at 0 in the main function, as usual, but when the Calc function is called, i is incremented to 1. So the next time the modification expression i ++ in the for statement is executed, i is changed to 2. Now the controlled block of the for statement is executed again, with i set to 2. Again, the call to Calc results in i being incremented an extra time, to 3, so the next execution of the for loop sets i to 4. The final call to Calc increments the value of i to 5, so the for loop terminates, having executed only three times rather than the five you would expect by looking at it. Now you can see why global variables are dangerous!
- Now what about the values that j takes on? Well, since the j in Calc is a static variable, it is initialized only once. Because it is a local static variable, that initialization is performed when Calc is called for the first time. So the first time Calc is called, j is set to 0. The arguments specified by main on the first call to Calc are 5 and 0; this means that, inside Calc, x and y have those values, respectively. Then the new value of j is calculated by the statement j = x + y + j;, or 5 in total. The return j; statement specifies this as the return value of Calc and this value is then added to 7 as specified by the assignment statement j = Calc(i + 5, i * 2) + 7; in main. That explains why the output statement in main displays the value of j as 12 the first time.
- It's very important to note that the variable j in main is completely unrelated to the variable j in Calc. Since they are local variables, they have nothing in common but their names. There is no risk of confusion (at least on the compiler's part), since we can access a local variable only in the function in which it is defined. Therefore, when we refer to j in main, we mean the one defined there; and when we refer to j in Calc, we mean the one defined there.
- Next, we call Calc again with the arguments 7 and 4. To compute these arguments from the expressions i + 5 and i * 2, you have to remember that i has been modified by Calc and is now 2, not 1 as we would expect normally. When we get to Calc, it displays the old value of j (5), left over from the previous execution of this function. This is because j is a local static variable; thus, the initialization statement static short j = 0; is executed only once, upon the first call to the function where it is defined. Once j has been set to a value in Calc, it will retain that value even in a subsequent call to Calc; this is quite unlike a normal auto variable, which has no known value at the beginning of execution of the function where it is defined. A new value of j is now calculated as 7 + 4 + 5, or 16, and returned to main.
- On return from Calc, the value of j in main is 23, as set by the assignment statement j = Calc(i + 5, i * 2) + 7;. We also don't want to forget that i is now 3, having been changed in Calc.
- Exactly the same steps occur for the last pass through the for loop: we call Calc with the new values of i + 5 and i * 2, which are 9 and 8, respectively, since i has been incremented to 4 by the for statement's modification expression i ++. Then Calc displays the old value of j, which is 16, and calculates the new value, which is 33. This is added to the literal value 7 and stored in j in main, resulting in the value 40, which is then displayed by the output statement.
- Don't get discouraged if you didn't get this one, especially the effects caused by a global i. Even experienced programmers can be taken by surprise by programs that use global variables in such error-prone ways.
|
www.steveheller.com steve@steveheller.com |