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.
Related
I am encountering problems in understanding the static identifier in the specific case of this program. The context of this program is a lecture about "pointers".
This program's job is to create a new name for a temporary file, it accomplish this (with the help of static int sequence) by creating a new name every time the function tmp_name is called.
first call –> "tmp0"
second call –> "tmp1"
...
[code]
#include <stdio.h>
#include <string.h>
/*******************************************************
* tmp_name -- Return a temporary filename *
* *
* Each time this function is called, a new name will *
* be returned. *
* *
* Returns *
* Pointer to the new filename *
*******************************************************/
char *tmp_name(void){
static char name[30]; /* The name we are generating */
static int sequence = 0; /* Sequence number for last digit */
++sequence; /* Move to the next filename */
strcpy(name, "tmp");
name[3] = sequence + '0';
/* End the string */
name[4] = '\0';
return(name);
}
int main(){
char *tmp_name(void); /* Get the name of temporary file, very first call */
char *name1; /* Name of a temporary file, second call */
char *name2; /* Name of another temporary file, third call */
name1 = tmp_name();
name2 = tmp_name();
printf("Name1: %s\nName2: %s\n", name1, name2);
return(0);
}
So the output of the program (since the printf function is called) is to print "tmp1" and "tmp2" ("tmp0" cannot be printed, and it is perfectly ok).
So the program is PERFECTLY WORKING, what is the problem then? The problem is that if i remove static from static char name[30] the program breaks. It prints this out:
Name1: \340\364\277\357\376
Name2: \340\364\277\357\376
I studied what static does mean and what it implies, for this reason the use of static int sequence is perfectly clear for me, but i really cannot understand why also the array [name] is declared statically.
char *stuff() {
char thing[100];
strcpy(thing, "what are you returning??");
return thing;
}
Now, what are you returning here?? A pointer. To what? Remember that non-static local variables are destroyed after the function returns. So, in char *data = stuff(); the variable data will be full of garbage since thing has been disposed of.
Static variables, however, are still there and are perfectly valid even when the function exits, so that pointer you're returning still points to the memory your program owns and that definitely contains the data you put there, while in the case of non-static variables, you lose control of this memory once the function exits, and thus any program may put anything in there, that's how you get this garbage data.
The problem is that if i remove static from static char name[30] the program breaks.
If you remove static for name, it becomes an object with automatic storage duration and returning it (i.e., pointer to a local variable) results in undefined behaviour. With static it works because name will have static storage duration (i.e., name object is alive throughout the execution of the program).
Alternatively you can allocate memory dynamically (e.g., using malloc) and copy the name into it and return it.
Let's start with the basics: §5.2.3 c11 standard N1570
The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
The italics present a nice idea - what it has to do with anything else? For static storage duration
An object whose identifier is declared without the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
So that means when you write static somevar it will live until the program ends in this case until main() ends. The storage duration of static variable is beyond the scope of the function. So returning a pointer pointing to it is valid. And it won't be illegal code.
Now let's see another
An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration, as do some compound literals.
That means when you remove the static from the variable name in this case and it is in enclosing block of the function - it is automatic storage duration.
And then comes the most important part in explaining why the second one fails
For such an object that does have a variable length array type, its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration.
such an object means here those with automatic storage duration. And as you see here when the enclosing block the function body ends - the value of pointer that you return from the function becomes indeterminate and accessing it is undefined behavior(Check the first paragraph).
This explains why you see what you see.(This is what you asked - what is happening and why is it so?) This is explanation standard wise for the given behavior.
If I have a function that is called A LOT of times, and that function needs an array of 16 pointers that will be updated with new pointers every time it's called, is this the right way to declare this array?
char** readUserInput() {
static char* cmds[16];
...
}
Will this array be initialized once?
Yes, static variables are only initialized once. By declaring the variable cmds you are declaring an array of 16 char*s. The array is initialized with zeroes. The array will never be initialized again.
Take this code as an example:
int i;
static char *cmds[5];
for (i = 0;i<5;++i) {
printf("%d ", cmds[i]);
}
It prints:
0 0 0 0 0
It is declared only once regardless of whether it houses the static storage specifier. Don't confuse declare with lifetime.
If the real question is "will there be only one instance of cmds, and will its content persist between calls?", then yes. It is declared with the static storage class specifier. Per §6.2.4.3 of the C11 standard
... Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup."
Static variables are only initialized/declared once and the static keyword is useful to provide a lifetime over the entire program, but limit their scope.
It is unclear whether you have to return that array from hot function. If yes, it has to be static or has to be passed as an argument. Even if not, then there is no difference in "speed" between static and auto-array, because your reuse scheme should anyway have means of [possibly no-op] preinitialization before call, and no matter what very first initial value was.
Drawback of static storage is that code becomes non-reentrant. Passing it as an argument would be more correct solution.
(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.
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.
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