Reputation: 108978
Consider the program
#include <stdio.h>
int main(void) {
for (int curr = 0; curr < 3; curr++) {
int prev;
if (curr) {
printf("%d\n", prev); //valid; prev has 0 or 1
}
prev = curr;
}
}
Is it valid?
What's the lifetime and scope of prev
?
There will be 3 distinct prev
s with lifetime and scope inside the for
loop.
The distinct prev
s may (but are not required to) share the same address.
Program is not valid.
There will be 3 prev
s with lifetime and scope inside the for
loop.
The prev
s will share the same address, behaving as if defined with static
.
Program is valid.
There will be 1 prev
, as if it was defined outside the for
loop.
Program is valid.
Note: question originated during discussion on this answer
Upvotes: 3
Views: 141
Reputation: 108978
Answer 1 is correct.
Three different and distinct prev
s that do not (need to) share address or value.
On every loop a different prev
will be "created" and "deleted".
Upvotes: 2
Reputation: 1130
ISO/IEC 9899:TC3 is perfectly clear about that:
In the original post, prev
has a constant address within the loop, but its value is indeterminate when evaluated. Therefore, the code exhibits undefined behavior.
I think this makes all of the answers in the original post (1-4) incorrect.
Upvotes: 2
Reputation: 81217
When using C89, or when using only the supplied looping constructs constructs in later versions of C, it's impossible for code to reach a location above an automatic object's declaration within the lifetime of the object. C99, however, added the ability to use goto
to transfer control from a point below a declaration to a point above within the lifetime of the object declared thereby. I'm not sure to what extent any non-contrived programs rely upon the fact that using goto
to transfer control above the declaration of a non-VLA object does not end their lifetime, but the Standard requires that implementations make allowance for such behavior, e.g.
void test(void)
{
int pass=0;
int temp;
int *p;
int result;
firstPass:
if (pass)
{
temp = *p;
goto secondPass;
}
pass++;
int q=1;
p=&q;
q++;
goto firstPass;
secondPass:
return temp + q;
}
the lifetime of q
would start when code enters test
, and extend throughout the execution of the function even if code branches to a point above the declaration. If execution reaches a declaration with an initializer, the value of the object is assigned at that time; if it reaches a declaration withou an initializer, the value of the object becomes indeterminate at that time, but if code jumps over the declaration the object retains its value.
Upvotes: 1
Reputation: 279
1
prev
is treated as an automatic variable that has a scope inside the loop instance
This means that at each iteration all the automatic variables are released and then re-acquired when the loop executes again.
Actually, the definition of the for-loop
is that the for statement executes each time (incrementing the variable, in this case) and testing the condition,
so even looking at the code you can see that the bracketed scope is finished
each time the loop ends.
Any guarantee of the address at which the local variable is allocated (or a register holding the value) is void. It is totally implementation-dependent.
Upvotes: 2