4

I have the concept of static local variables down pretty well: global lifespan, local scope. Similarly, I understand automatic variables are allocated/deallocated automatically when program flow enters and leaves the variable's context.

#include <stdio.h>

void test_var(void){
    static unsigned foo = 0;
    unsigned bar = 0;
    printf(" %u   %u\n", foo++, bar++);
}

int main(void){
    printf("Foo Bar\n");
    printf("--- ---\n");
    for(unsigned x = 0; x < 10; x++){
        test_var();
    }

    return 0;
}

As such, the previous example behaves as expected and prints the following output:

Foo Bar
--- ---
 0   0
 1   0
 2   0
 3   0
 4   0
 5   0
 6   0
 7   0
 8   0
 9   0

What confuses me is how the variables behave when not initialized:

#include <stdio.h>

void test_var(void){
    static unsigned foo;    /* not initialized */
    unsigned bar;           /* not initialized */
    printf(" %u   %u\n", foo++, bar++);
}

int main(void){
    printf("Foo Bar\n");
    printf("--- ---\n");
    for(unsigned x = 0; x < 3; x++){
        test_var();
    }

    return 0;
}

Output:

Foo Bar
--- ---
 0   2
 1   3
 2   4
 3   5
 4   6
 5   7
 6   8
 7   9
 8   10
 9   11

So the static variable behaves as expected -- getting a default value of 0 and persisting through the function calls; but the automatic variable seems to persist as well -- although holding a garbage value, it increments in each call.

Is this occurring because the behavior is undefined in the C standard, or is there a set of rules in the standard that explain this?

Vilhelm Gray
  • 11,516
  • 10
  • 61
  • 114
  • 3
    Looks a lot like undefined behavior to me. Add a few more variables and function calls around the test_var function and "fun" will probably ensue. – Michael Dorgan May 15 '13 at 17:54
  • 3
    It's undefined behaviour. It probably is because the variable `bar` is always placed at the same position and that is never overwritten between the calls. – Daniel Fischer May 15 '13 at 17:55
  • 1
    I am almost 100% positive this is a duplicate question. – Michael Dorgan May 15 '13 at 17:57
  • 2
    So the reason it appears to persist is probably because my code is so simplistic that the memory never gets overwritten? – Vilhelm Gray May 15 '13 at 17:57
  • possible duplicate of [What happens to a declared, uninitialized variable in C? Does it have a value?](http://stackoverflow.com/questions/1597405/what-happens-to-a-declared-uninitialized-variable-in-c-does-it-have-a-value) – Michael Dorgan May 15 '13 at 17:58
  • 1
    @VilhelmGray Very probably. If you call another function with a couple of arguments in the loop body too, that would have a good chance of overwriting the location where `bar` gets put. – Daniel Fischer May 15 '13 at 18:09

1 Answers1

1

The C standard says that the lifetime of an object is the time that storage is guaranteed for it ( see eg 6.2.4 of the ISO/IEC 9899:TC3 ). The lifetime of static and global variables is throughout the program and for this the above behavior is guaranteed by the standard. These values are initialized before program start-up. For automatic also objects are at a constant address but only guaranteed through out their life time. So although bar appears to remain alive over multiple function calls, you can't guarantee it. This is also why you should always initialize your variables, you can never know which variable was at the same spot before you use it.

I slightly adapted the program to also print the address of both the static and local variable:

#include <stdio.h>

void test_var(void){
    static unsigned foo;    /* not initialized */
    unsigned bar;           /* not initialized */
    printf(" %u   %u\t%p\t %p\n", foo++, bar++, &foo, &bar);

}

int main() {
    printf("Foo Bar\n");
    printf("--- ---\n");
    for(unsigned x = 0; x < 3; x++){
        test_var();
    }

    return 0;
}

This yielded the following output on my computer:

Foo Bar
--- ---
 0   33616  0x1067c  0xbee894fc
 1   33617  0x1067c  0xbee894fc
 2   33618  0x1067c  0xbee894fc

This shows that on my machine both the static foo and the automatic bar were at the same respective address for each call, but that is coincidental and the C standard doesn't guarantee that bar will always be at the same address.

Vilhelm Gray
  • 11,516
  • 10
  • 61
  • 114
hetepeperfan
  • 4,292
  • 1
  • 29
  • 47