Lifetime of a Variable
Variables not only have a scope (where can a variable be accessed), but also a so-called lifetime (when can a variable be accessed):
-
A global variable exists throughout the entire runtime of a program, i.e., from the moment the program starts until the program ends.
-
A local variable exists only during the execution of a function call:
-
The lifetime begins with entering the function.
-
The lifetime ends with leaving the function.
-
Task
Translate the program ex3.abc and execute it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @ <stdio.hdr> global a: int = 42; fn foo() { local b: int; printf("foo entered: b = %d\n", b); b = a; printf("foo leaving: b = %d\n\n", b); } fn main() { // printf("calling foo:\n"); foo(); // printf("calling foo:\n"); foo(); } |
On my computer, I get the following output:
theon$ abc ex3.abc theon$ ./a.out foo entered: b = 0 foo leaving: b = 42 foo entered: b = 42 foo leaving: b = 42 theon$
Your output may look different because, as we will see, we are dealing with “undefined runtime behavior” here.
If you carefully trace the control flow of the program and its output, you will find that it seems to contradict the statement about the lifetime of local variables. Go through the program line by line and understand when each output is generated.
Here are a few points to observe closely:
-
In line 8, the value of variable b is output before it is initialized. So, the value outputted during the first call to the foo function (in my case 1) is undefined.
-
In line 9, the value of b is overwritten with the value of a (i.e., 42).
-
During the second function call, in line 8, the value of b is output again before the variable is initialized. Now, the value 42 is outputted. This is the value the variable had at the end of the last function call. So, it seems that the local variable b has “survived” the last function call.
Remove the comments in line 15. Translate the program again and execute it. Two additional lines will be output. I get:
theon$ ./a.out foo entered: b = 0 foo leaving: b = 42 foo entered: b = 42 foo leaving: b = 42 theon$
You might see different values of b or the same. In my case (and on this machine) nothing changed.
Translate the program again, this time with optimization enabled. For example, with:
theon$ abc ex3.abc -O1 theon$
I get the following output:
theon$ ./a.out foo entered: b = -1073749400 foo leaving: b = 42 foo entered: b = 5252916 foo leaving: b = 42 theon$
Now the initial value of variable b is different each time foo is entered.
Conclusion
-
Local variables do not survive a function call.
-
Local variables are newly created at each function call and have an undefined value without explicit initialization.
-
Outputting an undefined value can result in output that depends on the calendar day, the time of day, personal perception, and the weather.