3

I'm trying to learn C using this tutorial. There is an example there that the author is tried to learn us what static storage class is.

This is that example :

#include <stdio.h>

/* function declaration */
void func(void);

static int count = 5; /* global variable */

main()
{
   while(count--)
   {
      func();
   }
   return 0;
}
/* function definition */
void func( void )
{
   static int i = 5; /* local static variable */
   i++;

   printf("i is %d and count is %d\n", i, count);
}

My question is: Why he/she is defined count as static? In the other words, what is the difference between the above program and the following program?

#include <stdio.h>

/* function declaration */
void func(void);

int count = 5; /* global variable */

main()
{
   while(count--)
   {
      func();
   }
   return 0;
}
/* function definition */
void func( void )
{
   static int i = 5; /* local static variable */
   i++;

   printf("i is %d and count is %d\n", i, count);
}

I mean, when we must use the first program and when we must use the second one?

2 Answers2

4

Defining your count as a global variable or a static one does not matter in your particular example (where each program has only one source file, i.e. one translation unit). But it does matter for i (which, without the static keyword, would become an automatic local variable), since it is declared inside a function. However, it would matter a big lot for any program made of several translation units (linked together to make the executable).

If you define a count global variable in two different translation units (i.e. in foo1.c and foo2.c) the linker would complain against multiple definitions (when you build your foo executable from foo1.o & foo2.o with gcc foo1.o foo2.o -o foo on your Linux system); if you defined a static int count; variable both in foo1.c and in foo2.c it is ok (but then you have two synonymous variables, each having its own address, and each implicitly initialized to 0; IMHO this is often poor taste, because it makes the source code less readable).

As an exception, you can declare without explicitly initializing it a global variable of the same name in two different translation units. The name refers to the same and unique global (initialized to 0).

So having

// in file foo1.c
int globalcount; // a global variable *declaration* 

and

// in file foo2.c
int globalcount; // a global variable *declaration*

is the same as having

// in file foo1.c
int globalcount = 0; // a global variable *definition* with initialization

and

// in file foo2.c
extern int globalcount;  // an external variable declaration

Actually, that external declaration should usually be in some header file foo.h which gets #include-d by both foo1.c & foo2.c.

Therefore, static variables (of the main program) are also invisible by plugins. Read more about visibility attribute (on Linux) to make a variable visible only by a single plugin or shared library (but not outside it).

Read wikipage on linkers & dynamic linkers then Levine's book linkers and loaders

Practically speaking, I would suggest to use unique names for non-local variables (both global and static ones), for readability and convenience (since it is easy to grep them); but sometimes you might want to have a few static variables with the same name in different compilation units. If you do, I suggest to comment why, and have some consistent naming conventions.

Look for examples in some free software coded in C.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Thank you for this complete answer. What happens if I define `int count` in foo1.c and `static int count = 5` in foo2.c? –  Jul 07 '15 at 08:38
  • 1
    Then in `foo2.c` you'll see the static variable. But you should not code this way (it is confusing for human developers and make your code unreadable) – Basile Starynkevitch Jul 07 '15 at 08:39
  • I think your answer need a small refinement. Here : _... if you defined a `static int count;` variables both ..._ I think I must initialize static variable in the point of definitions. right? –  Jul 07 '15 at 08:40
  • 1
    No, you need to declare static variables. Without initialization (and contrarily to `auto` or local variables) they are initialized to zero or -for pointers- to `NULL` – Basile Starynkevitch Jul 07 '15 at 08:41
3

static for a global variable makes it global only to that file (compilation unit). It will not be accessible from other files (compilation units)

gman
  • 100,619
  • 31
  • 269
  • 393