Thursday, August 28, 2014

static variable



Static variable



  • when applied to a variable declared inside a function, the value of that variable will be preserved between function calls.
  • when applied to a variable declared outside a function, or to a function, the visibility of that variable or function is limited to the "translation unit" it's declared in - ie the file itself. 
  • For variables this boils down to a kind of "locally visible global variable".

going to see following:


  • impact on life time
  • impact on the scope
  • where its stored in the memory
  • value of unintialized global and static variable


impact on the life time (returning the variable)
----------------------------

#include<stdio.h>

char** func1_Str();
char** func2_Str();

int main(void)
{
    char **ptr1 = NULL;
    char **ptr2 = NULL;

    ptr1 = func1_Str();
    printf("\n [%s] :: func1_Str() address = [%p], its returned address is [%p]\n",*ptr1,(void*)func1_Str,(void*)ptr1);

    ptr2 = func2_Str();
    printf("\n [%s] :: func2_Str()address = [%p], its returned address is [%p]\n",*ptr2,(void*)func2_Str,(void*)ptr2);

    printf("\n [%s] [%p]\n",*ptr1,(void*)ptr1);

    return 0;
}

char** func1_Str()
{
    char *p = "Linux";
    return &p;
}

char** func2_Str()
{
    char *p = "Windows";
    return &p;
}
output:
$ ./static

 [Linux] :: func1_Str() address = [0x4005d5], its returned address is [0x7fff705e9378]

 [Windows] :: func2_Str()address = [0x4005e7], its returned address is [0x7fff705e9378]

 [Windows] [0x7fff705e9378]
$
The above output makes it clear that once the lifetime of the local variable of the function ‘func1_Str()’ gets over then same memory address is being used for the local pointer variable of the function ‘func2_Str()’ and hence the third print is ‘Windows’ and not ‘Linux’.

So, now we see what that the root of the problem is the life time of the pointer variables. This is where the ‘static’ storage class comes to rescue. As already discussed the static storage class makes the lifetime of a variable equal to that of the program. So, lets make the local pointer variables as static and then see the output :

above problem corrected using static:

#include<stdio.h>

char** func1_Str();
char** func2_Str();

int main(void)
{
    char **ptr1 = NULL;
    char **ptr2 = NULL;

    ptr1 = func1_Str();
    printf("\n [%s] :: func1_Str() address = [%p], its returned address is [%p]\n",*ptr1,(void*)func1_Str,(void*)ptr1);

    ptr2 = func2_Str();
    printf("\n [%s] :: func2_Str()address = [%p], its returned address is [%p]\n",*ptr2,(void*)func2_Str,(void*)ptr2);

    printf("\n [%s] [%p]\n",*ptr1,(void*)ptr1);

    return 0;
}

char** func1_Str()
{
    static char *p = "Linux";
    return &p;
}

char** func2_Str()
{
    static char *p = "Windows";
    return &p;
}
output:
$ ./static

 [Linux] :: func1_Str() address = [0x4005d5], its returned address is [0x601028]

 [Windows] :: func2_Str()address = [0x4005e0], its returned address is [0x601020]

 [Linux] [0x601028]


impact on the scope
----------------------------

points need to be caputred:

in three.c file a is global variable and when compiled then a will be global in the executable and a in the four.c is also the global variable a and so problem arises.
this problem can avoided in two ways
way 1: can declare a in the three.c as static
way 2: instead of declaring the variable in four.c we can make a in four.c as extern

root@selvakumar-Lenovo-B460e:/C_pgms/extern-var# cat three.c four.c
int a=10;
void fun()
{
printf("\n%d\n",a);
}

#include<stdio.h>
 int a = 20;
int main()
{
 printf("\n%d\n",a);
 fun();
 return 0;
}
root@selvakumar-Lenovo-B460e:/C_pgms/extern-var# gcc three.c four.c
three.c: In function ‘fun’:
three.c:4:1: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
/tmp/cc8PMgA6.o:(.data+0x0): multiple definition of `a'
/tmp/ccbqbc2L.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
root@selvakumar-Lenovo-B460e:/C_pgms/extern-var#


way1:

Points need to be captured:

* so i made variable a in the file three.c as static and this is very same rule for the function declaration also

root@selvakumar-Lenovo-B460e:/C_pgms/extern-var/way1# cat three.c four.c
static int a=10;
void fun()
{
printf("\n%d\n",a);
}

#include<stdio.h>
 int a = 20;
int main()
{
 printf("\n%d\n",a);
 fun();
 return 0;
}
root@selvakumar-Lenovo-B460e:/C_pgms/extern-var/way1# gcc three.c four.c
three.c: In function ‘fun’:
three.c:4:1: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
root@selvakumar-Lenovo-B460e:/C_pgms/extern-var/way1# ./a.out

20

10
root@selvakumar-Lenovo-B460e:/C_pgms/extern-var/way1#

impact on storage:
  • irrespective of the global/local static variable its stored in the initialized/uninitialized memory region rather than stack memory space

#include<stdio.h>
static int initialized=1;      /* stored in initialized variables RW data segment */
staic int un_initialized;     /* (BSS) Uninitialized variable stored in bss data segment*/ *
int main()
{
static int a;                       /* Uninitialized static variable stored in bss data segment*/
static in a =100 /* Initialized static variable stored in DS*/
}


* for complete understanding of the all the variable you can go here:



root@selvakumar-Lenovo-B460e:/C_pgms/static-var# cat init_value.c
#include<stdio.h>
int g;  //g = 0, global objects have static storage duration
static int gs; //gs = 0, global static objects have static storage duration
int main()
{
  static int s; //s = 0, static objects have static storage duration
  printf("Value of g = %d", g);
  printf("\nValue of gs = %d", gs);
  printf("\nValue of s = %d", s);
  return 0;
}
root@selvakumar-Lenovo-B460e:/C_pgms/static-var# gcc init_value.c
root@selvakumar-Lenovo-B460e:/C_pgms/static-var# ./a.out
Value of g = 0
Value of gs = 0
Value of s = 0
root@selvakumar-Lenovo-B460e:/C_pgms/static-var#



Initialization of values:

In C, if an object that has static storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a NULL pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules;
— if it is a union, the first named member is initialized (recursively) according to these rules.



root@selvakumar-Lenovo-B460e:/C_pgms/static-var# cat init_value.c
#include<stdio.h>
int g;  //g = 0, global objects have static storage duration
static int gs; //gs = 0, global static objects have static storage duration
int main()
{
  static int s; //s = 0, static objects have static storage duration
  static int *ptr; //s = 0, static objects have static storage duration
  int *ptr2; //s = 0, static objects have static storage duration
  printf("Value of g = %d", g);
  printf("\nValue of gs = %d", gs);
  printf("\nValue of s = %d", s);
  printf("\nValue of s = %p", ptr);
  printf("\nValue of s = %d", *ptr2);
  return 0;
}
root@selvakumar-Lenovo-B460e:/C_pgms/static-var# gcc init_value.c
root@selvakumar-Lenovo-B460e:/C_pgms/static-var# ./a.out
Value of g = 0
Value of gs = 0
Value of s = 0
Value of s = (nil)
Value of s = 1539452
root@selvakumar-Lenovo-B460e:/C_pgms/static-var#

Can static variable included in the header file:

  • static variable can be defined in a header file, but this would cause each source file that included the header file to have its own private copy of the variable, which is probably not what was intended.




Reference:


No comments:

Post a Comment