Static Functions and Variables in C
Disclaimer:
Static is one of C's mysteries. It is odd because it has two completely unrelated uses. This is quite the little puzzle for a language learner. I looked around for a tutorial and I was unable to find one. I thought it may be useful to include one. I hope this proves useful. I was originally going to write about static functions in a future-- larger-- tutorial, but the tutorial I am designing and planning is too large. I decided to break it up into a couple smaller chunks. I am doing this static tutorial as one of those chunks.
Target Audience:
The audience I target is low to mid level C programmers. Although many books write about static functions and static variables very few actually explain when and how to use them-- or more importantly why they were included to begin with. I hope the audience can take at least 2 things from guide. First-- I hope the audience is able to use better encapsulation in C. Second, I hope the audience feels comfortable using static functions.
Side Bar:
I have personally never needed to use very many static variables, but I feel understanding them is important. On the other hand static functions are very useful and I personally think people do not use them enough.
Encapsulation:
Before we dive into the two meanings of static we should understand a little about encapcsulation first. Encapsulation basicly states we should limit the scope of our functions and variables. By limit the scope-- we essentially mean each variable and function should be give only the minimum visibility it needs to do its job.
You may be familiar with encapsulation in object oriented languages. If you are familiar with C++ or Java you may be familiar with scope modifying keywords such as public, private, protected etc. C does not have these scope modifying abilities.
However, non-object oriented languages like C also practice encapsulation. C has static functions as a way to maintain a little encapsulation. Understanding that and designing your functions and variables with it in mind will make you a better programmer. This brings us to static and why we should understand it.
The two odd meanings of static:
Static is incredibly odd in the sense that it has two very different-- almost opposite-- meanings. The first meaning applies when it is used with functions, and the second when it is used with variables. Let's take a closer look.
The first meaning-- static functions:
In order to test static functions you first need to be able to compile multiple source files-- I assume you have the ability to produce two different source files and compile them. With that addressed-- let's continue!
Static functions are much like private methods in Java or C++. A private method is a method which is only used by a class and can't be used outside of it. In C, we can declare a static function. A static function is a function which can only be used within the source file it is declared in.
First, I will give you a working example. There are two files-- main.c which is our main program. Our main program will call our custom mini-library called randomnum. We designed our randomnum library to consist of 2 functions. One is a public function called getRandomNum which returns a random number between 1-1000. The second function in the library is a private function called seedRandom. Anyone that has used rand in C knows you need to seed rand. In this case we make seed a private function so the outside source files can't mess with it. This is an example of encapsulation-- we hide the details of our library.
main.c
#include <stdio.h>
#include "randomnum.h"
int main(void)
{
printf("Random Number - %d\n", getRandomNum());
return 0;
}
randomnum.h
#ifndef RANDOMNUM_H #define RANDOMNUM_H #include <stdio.h> #include <stdlib.h> #include <time.h> /** * getRandomNum - returns a random number between 1-1000 * @return: an integer between 1-1000 */ int getRandomNum(void); /** * seedRandom - seeds our random function * @note: this function is private **/ static void seedRandom(void); #endif
randomnum.c
#include "randomnum.h"
int getRandomNum(void)
{
seedRandom();
return rand() % 1000 + 1;
}
static void seedRandom(void)
{
srand(time(NULL));
}
If all went well you should see the output-- a random number. Not so interesting. However, if we violate our scope we can make it a little more interesting. Here is a new main.c which violates the encapsulation.
#include <stdio.h>
#include "randomnum.h"
int main(void)
{
/* Error - private function seedRandom() */
seedRandom();
printf("Random Number - %d\n", getRandomNum());
return 0;
}
Well there you have it-- if you try to compile this you should get an error. Something along the lines of,
Quote
main.c:(.text+0xa): undefined reference to `seedRandom'
It is undefined because main can not see it-- it's hidden/private to the randomnum file(s).
In conclusion, static functions are great for sub-functions within a file. If you define some special functions that do busy-work inside a file multiple times it's probably best to declare them static and make sure the user (programmer) of your code does not use those same functions.
The second meaning-- static variables:
The second meaning is when static is used with a variable. This has nothing to do with static in the function sense. Static when used with a variable means the storage will be allocated at compile time and remain intact for the entire cycle of the program's execution. You may be thinking, "Isn't a global variable the same thing?" and you are right. A global variable uses static storage automatically. You probably hear people saying, "You should avoid global variables at all cost!" and they are also right. Global variables violate encapsulation because they don't hide data-- they simply give it to everyone. That is generally a bad style to program with.
I won't go into using global variables because it's something that should be avoided. I will show a snippet of how you could use static inside a function that returns a variable.
#include <stdio.h>
char* getBob(void)
{
static char bob[3] = "bob";
return bob;
}
int main(void)
{
char *name = getBob();
printf("%s\n", name);
return 0;
}
Try this code with static and try it without it.
Why declare bob as static? Because bob was declared inside a function. A function has auto (automatic) storage. That means when the function returns those variables are popped off the stack and never to be seen again (can be over wrote by new variables popped on the stack). If you used this code without static it may or may not display the correct name in this simple case. It's possible the memory would still be intact and display the name, but the behaviour is actually undefined if you don't include static. Static makes sure the variable is not automatic-- instead it is allocated for the remainder of the program.
To conclude static variables-- for the most part they are not needed (like in the global variable case). When declaring a global variable static storage is automatically assigned and using the static keyword is pretty much pointless. When using static in other contexts it may be useful if you need to return data that must remain intact for the remainder of the program. Think about it carefully before deciding to use it!
After thoughts:
Building a program is a lot like building a house. Building a house takes a lot of steps. As long as you break down these steps into small steps you can usually come to a better solution. Along the way you may want to hide some steps you took to build your house. Besides-- no home owner wants to see your plumbing and electrical wires hanging around. We want to hide these details from everyone. The only people that are concerned with them are the builders.
We should strive to build programs like houses. Let's not abandon encapsulation in C because it doesn't have the abilities that object-oriented languages have. Instead let's make the best of what we have-- static functions.
As for static variables-- use them with care.






MultiQuote





|