Question
I have seen the keyword static used in different places in C code. What does static mean in C, and is it similar to a static method or class member in C# where one implementation is shared across objects?
Short Answer
By the end of this page, you will understand that static in C does not mean the same thing it usually means in C#. In C, static mainly affects lifetime and visibility. You will learn how static behaves for local variables, global variables, and functions, and how developers use it in real C programs.
Concept
In C, the keyword static changes meaning depending on where it is used.
The two main ideas are:
- Storage duration: how long something exists in memory
- Linkage: whether a name can be accessed from other source files
1. static for a local variable inside a function
A normal local variable is created when the function starts and destroyed when the function ends.
A static local variable is different:
- it is created only once
- it keeps its value between function calls
- it is still only visible inside that function
Example:
#include <stdio.h>
void counter(void) {
static int count = 0;
count++;
printf("count = %d\n", count);
}
int main(void) {
counter();
counter();
counter();
return 0;
}
Output:
count = 1
count = 2
count = 3
If count were not static, it would reset to 0 every time counter() runs.
2. static for a global variable at file scope
A global variable normally has external linkage, which means other .c files can refer to it using extern.
If you mark a file-scope variable as static, it gets internal linkage:
- it can only be used inside that same
.cfile - other files cannot access it directly
Example:
static int cache_size = 128;
This is useful when a variable is part of a file's internal implementation and should not be exposed.
3. static for a function at file scope
A function declared static at file scope also gets internal linkage.
That means:
- the function can only be called from the same source file
- it is private to that file
Example:
static void helper(void) {
/* internal helper function */
}
This is a common way to hide implementation details in C.
Important: this is not object-oriented static
C does not have classes or objects in the C# sense. So static in C is not about "shared across objects".
Instead, think of static in C as controlling:
- how long data lives
- where names are visible
That is why the same keyword appears in multiple places with related but different effects.
Mental Model
Think of static in C like a private storage room or a locked office drawer.
- A normal local variable is like a sticky note you write during a meeting and throw away when the meeting ends.
- A static local variable is like a notebook kept in the room. Each time you come back, the old notes are still there.
- A static global variable or static function is like something kept in a locked office that only people in that office can use. Other offices cannot access it.
So the easiest mental model is:
- inside a function:
staticmeans “keep this value between calls” - outside a function:
staticmeans “keep this name private to this file”
Syntax and Examples
Core syntax
Static local variable
void func(void) {
static int x = 0;
x++;
}
Static global variable
static int total_users = 0;
Static function
static void log_message(const char *msg) {
/* ... */
}
Example 1: remembering state across calls
#include <stdio.h>
void next_id(void) {
static int id = 1000;
printf("Next id: %d\n", id);
id++;
}
int main(void) {
next_id();
next_id();
next_id();
return 0;
}
Output:
Next id: 1000
Next id: 1001
Next id: 1002
id is initialized only once, then it keeps its value.
Example 2: private helper function in one file
#include <stdio.h>
static int square(int x) {
return x * x;
}
int main(void) {
printf("%d\n", square(5));
return 0;
}
Here, square can only be used in this source file.
Example 3: static vs non-static local variable
#include <stdio.h>
void demo(void) {
int normal = 0;
static int saved = 0;
normal++;
saved++;
printf("normal = %d, saved = %d\n", normal, saved);
}
int main(void) {
demo();
demo();
demo();
return 0;
}
Output:
normal = 1, saved = 1
normal = 1, saved = 2
normal = 1, saved = 3
The normal local variable resets each call. The static one does not.
Step by Step Execution
Consider this program:
#include <stdio.h>
void visit(void) {
static int visits = 0;
visits++;
printf("visits = %d\n", visits);
}
int main(void) {
visit();
visit();
return 0;
}
Step-by-step
- The program starts.
- The
static int visits = 0;variable is allocated in static storage, not on the regular function stack. main()callsvisit()for the first time.visitsalready exists and starts at0.visits++changes it to1.- The program prints
visits = 1. visit()returns, butvisitsis not destroyed.main()callsvisit()again.- The same
visitsvariable is used again, still holding1. visits++changes it to2.- The program prints
visits = 2. - The program ends.
Key observation
The variable is local in scope but long-lived in storage duration.
That combination is what makes static local variables special in C.
Real World Use Cases
Where static is used in real programs
1. Private helper functions in a .c file
A file may contain support functions that should not be visible elsewhere.
static int parse_digit(char c) {
return c - '0';
}
2. Internal module state
A source file may keep internal counters, caches, or flags.
static int initialized = 0;
This avoids exposing internal details to the rest of the program.
3. Simple counters across function calls
Useful for IDs, call counts, retry tracking, or statistics.
void log_event(void) {
static unsigned count = 0;
count++;
}
4. One-time initialization logic
A function may need setup work only once.
void setup(void) {
static int done = 0;
if (done) {
return;
}
done = 1;
/* perform setup */
}
5. Encapsulation in C libraries
C has no private keyword for functions and globals, so static is often used as the file-level privacy tool.
Real Codebase Usage
In real C codebases, static is heavily used to keep modules clean and reduce accidental coupling.
Common patterns
File-private helper functions
static int is_valid_port(int port) {
return port >= 1 && port <= 65535;
}
This prevents other files from depending on internal helpers.
File-private configuration or state
static int debug_enabled = 0;
This keeps implementation details hidden inside one module.
Guarded initialization
void init_logger(void) {
static int initialized = 0;
if (initialized) {
return;
}
initialized = 1;
/* setup code */
}
This is a guard-clause style use of a static local variable.
Limiting exported symbols
In larger projects, developers mark only public API functions as non-static. Everything else is often static.
That helps with:
- cleaner module boundaries
- fewer naming conflicts
- easier maintenance
- less accidental misuse from other files
Caution in concurrent code
A static local variable is shared across all calls to that function, so in multithreaded programs it may need synchronization.
Common Mistakes
1. Assuming static means the same as in C# or Java
In C, static is not about class members or shared methods on objects.
Avoid this mistake
Think in terms of:
- storage duration
- file visibility
2. Expecting a static local variable to reset every call
Broken assumption:
void test(void) {
static int x = 0;
x++;
printf("%d\n", x);
}
A beginner may expect this to always print 1, but it prints 1, then 2, then 3.
3. Trying to call a static function from another file
static void helper(void) {
}
If another .c file tries to call helper(), it will fail because the function is only visible in its own file.
Avoid this mistake
Only use static on functions meant to stay private to that source file.
4. Declaring a variable static when shared hidden state is a bad idea
Using static local state can make code harder to test and reason about.
int next_number(void) {
static int n = 0;
return ++n;
}
This works, but now the function depends on previous calls.
Avoid this mistake
Use static only when remembering state is truly useful.
5. Confusing scope with lifetime
A static local variable is still local in scope.
Broken code:
void demo(void) {
static int x = 5;
}
int main(void) {
printf("%d\n", x); /* error: x is not visible here */
return 0;
}
x lives for the whole program, but it is only accessible inside demo().
6. Forgetting that static functions can help avoid name collisions
If many files define a helper named parse, making them non-static can cause linkage problems.
Better:
static int parse(const char *text) {
return 0;
}
Comparisons
static in different places in C
| Location | What static affects | Result |
|---|---|---|
| Inside a function | Storage duration | Variable keeps its value between calls |
| File-scope variable | Linkage | Variable is visible only in that source file |
| File-scope function | Linkage | Function is callable only in that source file |
C static vs C# static
| Feature | C | C# |
|---|---|---|
| Object-oriented meaning | No | Yes |
| Associated with classes/objects | No | Yes |
| Used for file-private functions | Yes | No |
| Used for local variables that persist | Yes | Not in the same way |
| Main ideas | Lifetime and linkage | Type-level members shared across instances |
Static local variable vs normal local variable
| Feature | Normal local | Static local |
|---|---|---|
| Visible inside function only | Yes | Yes |
| Created on each call | Yes | No |
| Keeps value between calls | No | Yes |
| Good for remembering state | No | Yes |
Cheat Sheet
Quick reference
Static local variable
void func(void) {
static int x = 0;
}
- Scope: inside the function only
- Lifetime: entire program
- Value persists between function calls
Static file-scope variable
static int count = 0;
- Scope: this source file
- Linkage: internal
- Other files cannot access it with
extern
Static function
static void helper(void) {
}
- Callable only inside the same
.cfile - Useful for private helper functions
Key rule
static in C usually means one of these:
- keep this value alive for the whole program
- keep this name private to this file
Important notes
staticdoes not mean “class-level” in C.- A static local variable is initialized once.
- A static local variable keeps state across calls.
- A static function cannot be used from another source file.
- A static file-scope variable helps hide implementation details.
FAQ
Is static in C the same as static in C#?
No. In C, static mainly controls lifetime and file visibility. In C#, static usually means a member belongs to the type rather than an instance.
What happens when a local variable is declared static in C?
It keeps its value between function calls and exists for the lifetime of the program.
Can a static function in C be called from another file?
No. A static function at file scope has internal linkage, so it is only visible inside its own .c file.
Can a static global variable be accessed with extern from another file?
No. A file-scope static variable is private to that source file.
Does a static local variable become global?
No. Its lifetime is long like a global, but its scope is still limited to the function where it is declared.
When should I use static on a function in C?
Use it when the function is an internal helper and should not be part of the module's public API.
Is static useful for encapsulation in C?
Yes. Since C has no private keyword for file-level functions and globals, static is commonly used to hide implementation details.
Mini Project
Description
Build a small C module that tracks how many times a helper function is called while keeping internal details private to one source file. This demonstrates both major uses of static in C: persistent local state and file-private functions.
Goal
Create a program where a public function prints a processed value and internally counts how many times processing has happened, without exposing the helper function or the counter to other files.
Requirements
- Create one public function that can be called from
main - Use a
statichelper function that is private to the source file - Use a
staticlocal variable to count how many times processing has occurred - Print the processed result and the call count each time the function runs
Keep learning
Related questions
2D Array Loop Order and Cache Performance in C
Learn why swapping nested loops changes 2D array performance in C, using row-major memory layout, cache locality, and practical benchmarks.
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.