Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why a global variable is defined as static in this C program? [duplicate]

Tags:

c

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?


1 Answers

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.

like image 172
Basile Starynkevitch Avatar answered Apr 24 '26 12:04

Basile Starynkevitch



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!