pmg
pmg

Reputation: 108978

program validity; lifetime and scope of variable defined inside loop

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?

  1. There will be 3 distinct prevs with lifetime and scope inside the for loop.
    The distinct prevs may (but are not required to) share the same address.
    Program is not valid.

  2. There will be 3 prevs with lifetime and scope inside the for loop.
    The prevs will share the same address, behaving as if defined with static.
    Program is valid.

  3. 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

Answers (4)

pmg
pmg

Reputation: 108978

Answer 1 is correct.

Three different and distinct prevs that do not (need to) share address or value.

On every loop a different prev will be "created" and "deleted".

Upvotes: 2

nilo
nilo

Reputation: 1130

ISO/IEC 9899:TC3 is perfectly clear about that:

enter image description here

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

supercat
supercat

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

Barak Friedman
Barak Friedman

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

Related Questions