4

What I have known so far is, multiple declarations inside a block produce an error message and also uninitialized local variable gives garbage value on printing.

But coming across an example of for loop in C has shaken my concept on the scope of variables.

Below is the code for the same:

#include<stdio.h>

int main()
{
    int i;
    for(int i = 5; i > 0 ; i--){
        int i;
        printf("%d ", i);
    }
}

The above code produces the output

0 0 0 0 0

I have two questions

  1. A for loop is considered as one block then how two different memories are allocated for two declarations of same variable i? And if the first line of for loop and its body are considered as two blocks, then how to identify different block?

  2. Inside the body of the loop, the variable i is uninitialized, then how is it taking the value as 0, as it should be having garbage value?

Please, explain this.

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39

2 Answers2

3

The scope of a variable declared in the first part of the for loop is all three parts of the for plus the loop body. In your case the body of the loop is a compound statement, and you declare another variable named i in that block, so it masks the i declared in the for.

So in your piece of code there are three relevant scopes:

  1. The body of the main function
  2. The three parts of the for loop.
  3. The body of the for loop.

And each of them is "internal" to the other, so a variable declared at one of these scopes masks a variable of the same name in a higher scope.

To further illustrate this, if we modify your code as follows:

int main()
{
    int i = 9;
    printf("outer i: %d\n", i);
    for(int i = 5;i>0;printf("middle i:%d\n", i),i--){
        int i = 7;
        printf("inner i: %d\n",i);
    }
    printf("outer i: %d\n", i);
}

The output is:

outer i: 9
inner i: 7
middle i:5
inner i: 7
middle i:4
inner i: 7
middle i:3
inner i: 7
middle i:2
inner i: 7
middle i:1
outer i: 9

As for why your code is printing 0 inside of the loop, an uninitialized variable may have any value, including 0. So just because it's printing 0 doesn't mean it's not garbage.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Thank You so much for the explanation. I understand 0 can be a garbage value too, but all my friends are also getting 0 as output in their system that won't be any coincidence I guess. So we were suspecting may be new compilers gives 0 always as garbage. Explain this, please. – Piyush Sharma Jul 20 '19 at 17:47
  • relevant link regarding seeing 0: https://stackoverflow.com/questions/21152138/local-variable-initialized-to-zero-in-c – Jimbo Jul 20 '19 at 17:56
1

A block is anything in curly braces. A block doesn't have to follow a for do, while, if, etc. Literally any set of statements can be enclosed in their own block scope using curly braces.

The i in the for loop is not in the loop body scope since it is outside the curly braces. The i in the block is indeed uninitialized and contains garbage. Garbage usually just means "whatever was there before". As often as not, that value will be zero. That doesn't make it any less garbage.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
  • I understand 0 can be garbage value, but all my friends were also getting same output as 0 in their systems and i don't think that would be any coincidence. That's why i had to ask this – Piyush Sharma Jul 20 '19 at 19:29
  • @Piyush. Most memory has an expectation value of zero. Your question is quite reasonable. – Mad Physicist Jul 20 '19 at 20:24