cscopeblocklocal-variables

how does buf retain data in the next iteration although we are re-declaring it every time?


"Buf" should destroy after line #28, as it is local to if block and we are re-declaring then it may have some different values or at least a different memory address when re-declared.

I think, Luckily getting the same address on each declaration but can’t rely on it, isn’t it? Or a different reason?

Code:

#include <stdio.h> 
int main() 
{ 
    int i=0, j=0, k=0; 

    while(3 > j) 
    { 
        if(2 > j) 
        {
            char buf[10]; 
            if (0 == j) 
            { 
                for(k=0; k<10; k++) 
                { 
                    buf[k] = 48 + k; 
                }
            } 
            puts(buf); 
        }               // line 28
        j++; 
    } 
    return 0; 
}

Solution

  • #include <stdio.h>
    
    int main() {
      int i=0, j=0, k=0;
      while(3 > j) {
        if (2 > j) {
          char buf[10];     // <---- block scope in "auto" context
          if (0 == j) {
            for(k=0; k<10; k++) {
              buf[k] = 48 + k;
            }
          }     // <---- end of block for the variable char buf[]
          puts(buf);
        }
        j++;
      }
    
      return 0;
    }
    

    You say

    It should destroy after line #28 (end of block) and as we are re-declaring then it should have some garbage value or at-least different memory address.

    For the vast majority of the C compilers, a declaration without any initializer does not generate any code, it only reserves same space in memory. If that declaration is in global scope, then its memory is cleared once at the start of the program, but in a way which has little to do with "code": all global declarations are put in a special area that gets cleared at the start of runtime.

    The code after the declaration (... buf[k] = ...) refers to a certain memory address, the one reserved for buf[10]. It is unlikely that, executing the block more than once, the instructions refer to different memory address - the code is compiled once... so the declaration and the subsequent code are assigned a memory address only once.

    Given that the storage is auto, it contains garbage, as stated in previous comments. Even the results of a previous computation are to be considered "garbage". Or, if someone prefers, say "indeterminate". The compiler (and the runtime) does not initialize "auto" variables.

    If you want to retain values between iterations, you declare the variable outside the block. If you don't want, you declare your variables inside the block, and ensure to fill all the data. Note that you are not doing that anyway: a string in C (buf passed to puts()) must be terminated by a NUL, but you don't put that NUL into the string.

    What happens here (lack of NUL apart), is that the variable gets some memory which is only touched in that block, so it retains the previous value - but there is absolutely no warranty it would do this in other contexts (different machine, different compiler).

    Put it in other words: for this sample code, there is no initialization and no destruction implicitly made. There are simply a declaration which reserves some memory, and your code which read and writes into that memory.