-1

The output of the following code is 0.

int account=2;

int main()
{
    static int account;
    printf("%d",account);
    return 0;
}

Why it picked static variable over global variable? Because what I understand is that both global and static variables are stored in the heap and not in function stack , right? So what method it uses to use select one over another?

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    shadow rule, if you don't want this behavior just don't name your variable the same. – Stargateur Sep 12 '18 at 15:23
  • In practice *never* have two variables of the same name visible in some common location (this is a coding rule) – Basile Starynkevitch Sep 12 '18 at 15:24
  • 3
    Note, that `static` or not `static` - it won't change anything. The local will be "picked" in any case. – Eugene Sh. Sep 12 '18 at 15:27
  • Meaning that **static int account** is local variable. I am asking this because I thought that static and global are stored separately in memory , so that none of them is local to function. Please correct me if I am wrong. –  Sep 12 '18 at 15:30
  • 1
    The way it is stored is unrelated to the scope rules. – Eugene Sh. Sep 12 '18 at 15:32
  • Oh Okay. Got it! –  Sep 12 '18 at 15:33
  • But note, that `static` *will* affect the scope of a *global* variable, and will restrict it to the translation unit. – Eugene Sh. Sep 12 '18 at 15:35
  • translation unit?? –  Sep 12 '18 at 15:35
  • 1
    Usually - a single source file. – Eugene Sh. Sep 12 '18 at 15:36
  • 1
    Neither of those variables will be stored in the heap. [Where they end up depends on if they're initialized.](https://stackoverflow.com/questions/93039/where-are-static-variables-stored-in-c-and-c#93411) – Reticulated Spline Sep 12 '18 at 16:17
  • Not clear what you are asking. `static` variables **are** have a "global" lifetime. "global" is not a standard term; what so you mean? – too honest for this site Sep 12 '18 at 17:15
  • @EugeneSh.: Ehm, … no. - wait, "restrict" in which sense? This question and the comments mix just way too many concepts. OP should first learn about the standard terminology; that should also make most of the question irrelevant. – too honest for this site Sep 12 '18 at 17:16
  • One really important point here is that by defining the inner variable static, you have enforced zero-initialization! This is the main reason you see 0 instead of an unspecified value – xaviersjs Nov 03 '18 at 22:53

5 Answers5

26

If multiple variables exist with the same name at multiple scopes, the one in the innermost scope is the one that is accessible. Variables at higher scope are hidden.

In this case you have account defined in main. This hides the variable named account declared at file scope. The fact that the inner variable inside main is declared static doesn't change that.

While the static declaration on a local variable means that it is typically stored in the same place as a global variable, that has no bearing on which is visible when the names are the same.

dbush
  • 205,898
  • 23
  • 218
  • 273
7

Consider this small self explaining program:

#include <stdio.h>

int bar = 123;     // global variable, can be accessed from other source files

static int blark;  // global variable, but can be accessed only in the same
                   // source file

void foo()
{
  static int bar;  // static variable : will retain it's value from
                   // one call of foo to the next
                   // most compilers will warn here:
                   // warning  declaration of 'bar' hides global declaration

  printf("foo() : bar = %d\n", bar);  // won't use the global bar but the
                                      // local static bar
  bar++;
}

void quork()
{
  int bar = 777;   // local variable exists only during the execution of quork
                   // most compilers will warn here as well:
                   // warning  declaration of 'bar' hides global declaration

  printf("quork() : bar = %d\n", bar);  // won't use the global bar but the
                                        // local bar
  bar++;
}

int main() {
  foo();
  foo();
  printf("main() 1 : bar = %d\n", bar);
  bar++;
  quork();
  quork();
  foo();
  printf("main() 2 : bar = %d\n", bar);
  printf("blark = %d\n", blark);
}

Output:

foo() : bar = 0
foo() : bar = 1
main() 1 : bar = 123
quork() : bar = 777
quork() : bar = 777
foo() : bar = 2
main() 2 : bar = 124
blark = 0
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
3

Just to clarify for future readers, global and static variables are not stored in heap or stack memory. https://www.geeksforgeeks.org/memory-layout-of-c-program/

They will either be stored in initialized data or uninitialized data.

Thats not the main question here, which was answered by dbush, but it is a misunderstanding in the original question.

Bwebb
  • 675
  • 4
  • 14
2

Short answer: encapsulation.

static describes both lifetime and visibility of a variable, and its meaning changes depending on the context. My opinion is that it is one of the more useful and important language features for encapsulation in c. Ignoring the complex relationship to extern, here's a simplified description:

static variables defined at the file level have program lifetime and compilation unit visibility. This means all functions in a .c file can access/modify the variable, but other .c files won't know about the variable. This is super useful for making sure variables used across functions with a compilation unit don't accidentally link with variables in other compilation units. Personally, I highly recommend all file variables to be static by default. Only remove the static specifier if you really want another compilation unit to have access to it (although a getter function may be safer)

Variables declared static within a block scope (most importantly function scope) have program lifetime, and scope visibility. That means it functions as if you declared the variable globally in the file, but only code within that block scope can see it. It also means from one call to the next, the variable does not get destroyed and state can be transferred from call to call.

One really important difference with static variables is that they are default-initialized to zero. This differs from all other variables in c, and is the reason your program prints the value 0. Often times with trivial programs we don't notice the difference because the stack hasn't been polluted with variables yet, but it becomes critical for any program of size.

The most common use for this that I have seen is to enable one-time initialization within a scope. They are also extremely useful for synchronization primitives like pthread_mutex_t. One time I even implemented a state-machine with function-scope static variable.

an example:

int started;//oops, anybody in the entire program can change this value, especially with such a common name!
static int lastCall;

int callCount(void)
{
    // This is default-initialized to 0
    static int functionStaticVariable;

    //Increment each time I'm called
    ++functionStaticVariable;

    //tell the outside world that I'm the one who was called last
    lastCall = 1;

    //return (a copy of) my internal state.
    return functionStaticVariable;
}

char *getSharedMemory(unsigned int bytes)
{
    // Here I cannot see functionStaticVariable, but I can see globalVariable
    //functionStaticVariable++; // this would cause a compilation failure

    // static pointer is default-initialized to zero (i.e. NULL)
    static char *sharedMemory;
    if(sharedMemory == 0)
    {
        // This block only executes once, the first time the function is called.
        // Actually this is a nice side-effect because it means if the function is never called we don't clutter the stack with unused memory
        // Although we will probably never free this memory
        sharedMemory = (char *)malloc(bytes);
    }

    // tell the outside world that this function has been called
    lastCall = 2;//valid

    //Woah, this is such a bad idea, but actually does _not_ return memory that gets invalidated
    return sharedMemory;
}

Hopefully you can see with this pattern you could protect a variable by placing it inside a function and doing optional things like acquiring a mutex-lock in order to allocate the memory. You could even implement the double-lock pattern this way.

I secretly wish that all C++ programmers learned good c encapsulation, because actually the language really encourages it. You can do an incredible amount by placing only functions that need to communicate with each other together in a compilation unit. In a non-OOP language, this can be very powerful.

Full details of static and extern are described by https://en.cppreference.com/w/c/language/storage_duration.

xaviersjs
  • 1,579
  • 1
  • 15
  • 25
0

The pragmatic reasoning behind why innermost variable decaration should be the one used: you're not always in control of what's outside your code. You want to be able to write a function that certainly works. If other programmers (say, in a larger team) could break your code just by the way they name variables in other parts of the code, programming would be more of a pain than it is now.

rioted
  • 1,076
  • 13
  • 24