Variable scope controls where in a program a variable can be accessed. In C, a variable’s scope is determined by where it is declared: variables declared outside all functions have file scope (global), while variables declared inside a function or block have block scope (local). A third kind — static local variables — persist between function calls but remain invisible outside their function.
The original post had main() without a return type and broken \n escape sequences throughout. This rewrite demonstrates all three scope types with a single clear program and output.
Three Kinds of Variables
| Kind | Where declared | Lifetime | Initial value | Visibility |
|---|---|---|---|---|
| Global | Outside all functions | Entire program run | Zero (guaranteed) | All functions in the file |
| Local | Inside a function or block | Until the enclosing block exits | Garbage (undefined) | Only inside its block |
| Static local | Inside a function, with static keyword |
Entire program run | Zero (guaranteed) | Only inside its function |
C Program for Global and Local Variable Scope
/* Global vs local variable scope in C
* Covers: global (file scope), local (block scope), static local
* Compile: gcc -ansi -Wall -Wextra scope.c -o scope */
#include <stdio.h>
int counter = 0; /* global: visible to all functions, zero-initialized */
void increment(void)
{
int local_count = 0; /* local: re-initialized every call */
static int call_count = 0; /* static local: persists between calls */
counter++;
local_count++;
call_count++;
printf(" increment() call #%d: counter=%d, local_count=%d, call_count=%d\n",
call_count, counter, local_count, call_count);
}
void shadow_demo(void)
{
int counter = 100; /* local counter shadows the global counter */
/* The global 'counter' is inaccessible by name here — shadowed */
printf(" shadow_demo(): local counter=%d (global is hidden by shadow)\n", counter);
}
int main(void)
{
printf("Before any calls: global counter = %d\n\n", counter);
printf("Calling increment() three times:\n");
increment();
increment();
increment();
printf("\nAfter 3 calls: global counter = %d\n\n", counter);
printf("Demonstrating local variable shadowing:\n");
printf(" (global counter before shadow_demo: %d)\n", counter);
shadow_demo();
printf("After shadow_demo(): global counter still = %d\n", counter);
return 0;
}
How to Compile and Run
gcc -ansi -Wall -Wextra scope.c -o scope
./scope
Sample Output
Before any calls: global counter = 0 Calling increment() three times: increment() call #1: counter=1, local_count=1, call_count=1 increment() call #2: counter=2, local_count=1, call_count=2 increment() call #3: counter=3, local_count=1, call_count=3 After 3 calls: global counter = 3 Demonstrating local variable shadowing: (global counter before shadow_demo: 3) shadow_demo(): local counter=100 (global is hidden by shadow) After shadow_demo(): global counter still = 3
Output Analysis
- counter increments from 1 to 3 — the global counter is shared between main and increment(). Every call to increment() modifies the same variable.
- local_count is always 1 — it is declared and initialized to 0 inside increment() on every call. As soon as the function exits, local_count ceases to exist. The next call creates a fresh copy starting at 0 again, then increments it to 1.
- call_count reaches 3 — the static local call_count persists between calls like a global, but it is only visible inside increment(). It acts as a per-function call counter.
- shadow_demo prints 100, not 3 — the local variable named counter inside shadow_demo shadows the global. The global is untouched — it remains 3 as shown by main’s print after the call.
Code Explanation
- Global initialization —
int counter = 0at file scope. Globals are zero-initialized by the C runtime even without the explicit= 0; the explicit initialization is included for clarity. Never assume local variables start at zero — only globals and static locals do. - static local call_count — the
statickeyword changes storage duration from automatic (destroyed on return) to static (lives for the whole program). Useful for counting function calls, caching computed values, or generating unique IDs. - Shadowing — when a local variable has the same name as a global, the local takes precedence inside its block. The global still exists and is unchanged, but it is invisible by name. This is a common source of bugs in C when a loop variable shadows a function parameter or global.
- Why avoid globals — globals make functions harder to test (each call depends on external state) and can cause bugs when multiple functions modify the same global in unexpected order. Prefer passing values as function arguments and returning results. Use globals only for truly program-wide state (e.g., a running mode flag, a signal handler result).
What This Program Teaches
- Automatic initialization — globals and static locals are guaranteed to be zero-initialized before main() runs. Local variables are not — they contain whatever bytes happen to be on the stack at that moment. Uninitialized local variables are one of C’s most common bugs.
- Storage duration vs scope — scope is about visibility (where can you write the name?); storage duration is about lifetime (when does the memory exist?). A static local has block scope (only visible inside its function) but static storage duration (lives forever).
- Function-level state with static locals — static locals are a common idiom for caching: compute something expensive on the first call, save it in a static local, and return the cached value on subsequent calls — without exposing it as a global.
- Shadowing is legal but dangerous — compilers warn about shadowing with
-Wshadow. Good practice is to name variables distinctly to avoid shadowing — it is a common source of hard-to-find bugs.
Related Programs
- extern Variable in C
- sizeof Data Types in C
- All Data Types in C
- Command Line Arguments in C
- Pointers in C — Complete Guide
Recommended book:
The C Programming Language — Kernighan & Ritchie (India) |
(US)
|
C Programming: A Modern Approach — K.N. King (India) |
(US)
Practice what you learned: C Aptitude Questions — or try our C Programming Quiz App on Android.