C Storage-class differences? - c

What is the difference between a variable declared as an auto and static?
What is the difference in allocation of memory in auto and static variable?
Why do we use static with array of pointers and what is its significance?

AUTO (default), Static, Extern & Register are the 4 modifiers for a variable in C.
auto : The default storage-class for a C variable. (i.e. no need to explicitly specify auto).
static : Changes the lifetime of the variable. (retains the scope, no
change).
This means, during runtime, the OS does NOT of delete the variable from memory once the function( containing the variable exits) and initialise the variable every time the function is called.
Rather the static variable is initialised ONLY the first time the function (containing it is called). Then it continues to reside in the memory until the program terminates.
in other words STATIC effectively makes a variable GLOBAL in memory, but with only LOCAL access.
Where your statics are stored depends on if they are 0 initialized or not.
0 initialized static data goes in .BSS (Block Started by Symbol),
non 0 initialized data goes in .DATA
One must note that, though static-variables are always in the memory, they can only be accessed ONLY from the local scope (function they are defined in).
extern : Used to signal to the compiler that the extern-definition is simply a placeholder, and the actual definition is somewhere else. Declaring a variable as extern will result in your program not reserving any memory for the variable in the scope that it was declared. It is also common to find function prototypes declared as extern.
register : Signals the compiler to Preferrably used a CPU-register (and not RAM) to store this variable.
Used to improve performance, when repeated access to the variable is made (for ex: loop counter variables).

I'll assume if you're talking about auto variables you probably mean local variables in a function. auto is the default, it means the variable is allocated on the stack when the function is called and deallocated when the function returns. static means the variable is allocated once the first time the function is called, and stays allocated for the rest of the program. This means:
int foo() {
static int x = 0;
return x++;
}
printf("%d\n", foo()); // Outputs 0
printf("%d\n", foo()); // Outputs 1
printf("%d\n", foo()); // Outputs 2

Related

Function maintains internal state in C

How can a function in C maintain it's internal state?
For example strtok() - when calling strtok(NULL, del) the function continue working on a previous string.
It contains internal variables to keep track of things, declared as static. This is also the very reason why such functions aren't safe to use in multi-threaded programs.
This is done by declaring local variables as static:
unsigned int some_state_function( void )
{
static unsigned int internal_state = 0; // keeps track of the number
... // of times the function has been
return internal_state++; // called - useless, but illustrative
}
The variable internal_state has static storage duration, meaning storage for it is allocated and initialized at program startup and held until the program terminates; its lifetime extends beyond the lifetime of the function. In this case the initialization is redundant (static objects are initialized to 0 or the equivalent), but it's there to illustrate the concept - the initialization occurs once, at program startup, not when the function is called.
However, the identifier internal_state is local to some_state_function - it's not visible outside the function.
strtok does something similar - it has a local static pointer that keeps track of the string you're processing.

C: How does C "ignore" subsequent initializations of local function variables when static?

(C beginner alert)
Wikipedia define a static variable as, ".... a variable that has been allocated statically—whose lifetime or "extent" extends across the entire run of the program. "
Then it goes on to give an example in C:
#include <stdio.h>
void func() {
static int x = 0;
/* x is initialized only once across four calls of func() and
the variable will get incremented four
times after these calls. The final value of x will be 4. */
x++;
printf("%d\n", x); // outputs the value of x
}
int main() { //int argc, char *argv[] inside the main is optional in the particular program
func(); // prints 1
func(); // prints 2
func(); // prints 3
func(); // prints 4
return 0;
}
Here's my issue: variable x, when defined as static, doesn't hold its value for the entire run of the program. In fact, it does quite the opposite, namely, for any subsequent call of func(), it has the value it was assigned in the previous calling. It's only when I remove the static keyword that x retains its value of 0 no matter how many times func() is called.
So:
1) Is Wikipedia's explanation inaccurate/misleading, and if so, how would you better explain the nature of a static variable?
2) What is actually happening under the hood on the second and subsequent calls of func() such that the initialization of x to 0 is effectivey being ignored?
You simply misunderstand the quoted explanation. What it means to say that a variable's "lifetime" extends to the whole program is that it is allocated in memory once, initialized once, and any changes made to it are reflected at the same memory location--that memory is allocated for the life of the program. Subsequent calls to the function will find the contents of that memory (the value of x) as they left it. They are still allowed to change the value, but it will always be the same piece of memory.
When you remove the "static", you're telling the compiler to allocate a new variable "x" each time the function is called, assign it 0, and discard it when the function returns. On the next call, an entirely different variable X will be created, assigned 0 again, and discarded again. This variable's "lifetime" is thus only inside the function.
This is an entirely separate concept from the variable's "scope", which is who can see and change the variable: it's scope is still inside the function, even when static.
The local static variables are located in the .bss section along with the global ones. So their initialization is effectively "taken out" of the function and moved to the same place where global statics are initialized. So, basically, declaring some variable as local and static in some function is only limiting it's scope to this function, but by other means it is not different from any other static variable.
The Wikipedia entry is neither misleading nor incorrect; it says the variable's lifetime extends across the lifetime of the program (even before func is called), which is exactly the case. A single instance of x is created and initialized once at program startup and will persist until the program exits, retaining the last value written to it from each call to func. Think of it as a "global" variable, but only visible from within func.
If you remove the static storage class qualifier, then x only exists for the lifetime of func; each call to func creates a new instance of x, which is initialized to 0.

What is the purpose of declaring the array as static in the function?

I have created a function (eg: fun()) and called it from the main function.I have also created an array in the function and I am returning the base address of the array to an integer pointer in the main function.If the array is declared as static in the function fun(),the array elements are properly displayed in the main function.If not,some garbage values are being printed.But the vice versa of this is working fine.That is,decalring an array in the main function and printing it in an another function by passing the base address.So what is the use of declaring the array as static?What is the correct explanation for it?
If an object is declared static in a function, it is essentially a global and permanent, and is not re-initialized every time the function is called like other local variables.
If you have a non-static object which is local to a function, and you return its address, by the time the caller does something with the address the object has gone out of scope because you are no longer in the body of the called function, and the region of memory your pointer refers to has undefined data in it, regardless of what you put there before. If the object was static then it does not fall out of scope.
If you have an object local to main, and you call a function from main and pass a pointer to this object, that object is still alive as far as the program is concerned, because you are still "in" the main function, and will return to it when you leave the body of the called function, so there is no problem referring to that region of memory. This has nothing to do with main: try the same thing from a different function.
Incidentally, none of this has anything to do with arrays, and the whole discussion applies to any kind of object.
If array declared as static then the array remains alive even after the execution of the function call and hence you can access the elements of the array.
Actually, static arrays are allocated in a different section of memory and is not allocated in the function stack frame. So it does not matter even if the function call is over, the array is still there.
If you do not declare the array static, then the array "disappears" when you leave the function. In fact, all of the variables that you declare in a function that are not static only exist as long as the function is executing. After return from the function, the variables are de-allocated from the heap. This is called the "scope" of a variable, the area in the code where the variable exists.
In your case, you are returning a pointer to an area where your array once was, when the function was executing, but by the time that the main uses the pointer, the area where the array once was has been overwritten.
Objects can have one of three storage durations: auto, static, or dynamic.
Objects with auto storage duration have storage allocated for them immediately following the point they are defined, and that storage is only held for the duration of the current scope; once that scope is exited, the object ceases to exist. For example:
void foo( int x ) // storage for x is set aside here
{
int bar; // storage for bar is set aside here
if ( x > 0 )
{
int i; // storage for i is set aside here
...
} // storage for i is released here
} // storage for x and bar is released here
The variable i only exists within the scope of the if statement; bar and x only exist within the scope of the function. Once the function exits, none of those variables exist anymore, and any storage allocated for them is now available for someone else to use1.
Objects with static storage duration have storage allocated for them when the program starts, and that storage is held until the program exits. Anything declared at file scope (outside of any function) or with the static keyword has static storage duration:
void foo( int x ) // storage for x is set aside here
{
static int bar; // storage for bar was set aside at program start
...
} // storage for x is released here; storage for bar will
// be released when the program exits
This is the reason you see the behavior you do; when the array is not declared static, the storage for it is released after the function exits, and someone else is free to overwrite it. When you declare it static, that storage is held until the program exits, so noone else can use it.
Objects with dynamic storage duration are allocated manually using malloc, calloc, or realloc, and held until explicitly released with free.
1. In practice, the storage for x, bar, and i is usually set aside at function entry and held until the function exits, but logically speaking you can't expect there to be any storage for i outside the scope of the if statement, meaning any pointers to i would not be valid outside of the if statement.

Is there any difference between the size of memory allocated for the following types of declaration:

i) static int a, b, c;
ii) int a; int b; int c;
I am not sure as to how will the memory be allocated for these types of declaration. And if these declarations are different then how much memory is allocated for each declaration?
static int a,b,c;
will allocate three ints (probably 32bits each, or 4 bytes) in the DATA section of your program. They will always be there as long as your program runs.
int a; int b; int c;
will allocate three ints on the STACK. They will be gone when they go out of scope.
There is no difference between the size of memory for
static int a,b,c;
int a;int b;int c;
Differences occur in the lifetime, location, scope & initialization.
Lifetime: Were these were declare globally, both a,b,c sets would exist for the lifetime of the program. Were they both in a function, the static ones would exist for the program lifetime, but the other would exist only for the duration of the function. Further, should the function be called recursively or re-entrant, multiple sets of the non-static a,b,c, would exists.
Location: A common, thought not required by C, is to have a DATA section and STACK section of memory. Global variables tend to go in DATA as well as functional static ones. The non-static version of a,b,c in a function would typically go on in STACK.
Scope: Simple view: Functionally declared variables (static or not) are scoped within the function. Global variables declared static have file scope. Global variables not declared static have the scope of the entire program.
Initialization: follows along the same track as lifetime. Globally declared a,b,c, static or not, are both initialized at program start. If a,b,c are in a function, only static ones are initialized (at program start). Functional non-static a,b,c are not initialized.
Optimization may affect location, especially for the functional non-static a,b,c which could readily be saved in registers. Optimization may also determine that the variable is not used and optimizing it out, thus taking 0 bytes.
The variables that are defined as static will allocated in data segment at compile time. The same is true for global variables even though they are not static. Non-static variables defined within a block are allocated on the stack when the block is entered at runtime and are deallocted when th block is exited.
The amount of memory allocated is implementation dependent. The standard requires that an int is large enough to hold a 16-bit (2 byte) valued, but is can be larger. Most compilers you are likely to use now adays use 32-bit ints.
If we assume that 2nd declaration is inside function, than As Bard and Nashant already said these will be allocated in different memory sections (OS and compilers dependent).
But though variable size will be of the same size, they CAN consume different amount of memory. If function (from 2nd declaration) is called recursively for example, there will be multiple instances of variables from 2nd declaration.

C pointer array allocation

When are variables in main() allocated? Especially how much memory is allocated for the pointer to arrays arr and 2d in the following:
int main()
{
float a, b;
int *b;
float *(arr)[6];
float *(2d)[5][5];
}
Are these considered auto, global, or static?
All these variables are automatic: global variables need to be declared outside the scope of a function; static variables need to have a static modifier.
The exact size is system-dependent. You can find out by printing sizeof(arr), sizeof(b), etc.
The exact time of allocation of automatic variables is compiler-dependent: some of them are allocated upon entering the function, some are upon entering a block where they are used, and some may be optimized out, and not allocated at all.
Memory for all the local variables declared inside a function will be allocated during run time, before executing a function. For each function an activation record will be created in the stack of the process memory, which will contains all the local variables. Once the function execution is completed activation record will be poped out.
All the variables declared inside a function are consider as auto only, unless it is explicitly declared as static or register. Variables declared outside a function will be considered as global.
If a variable is declared inside or outside a function as static, means memory allocation will be done at compile time itself, which will be in data segment(or bss).
All the pointer variable is going to store some virtual address(of variable of any type or function). So size of a pointer variable is 4 bytes in case of 32 bit machine and 8 bytes in case of 64 bit machine.

Resources