Need Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.
Variable Scope Examples: Shadowing, static Locals, extern and Dangling Pointers
Nine compiled examples with real output: shadowing, block scope errors, static counters, one-time init flags, stack frames, dangling pointer warnings, internal linkage and extern. Study this one of the variable scope examples before the next.
Variable Scope Examples: What This Page Covers
These variable scope examples are compiled and run for real. Each one isolates a single rule about where a name is visible or how long its storage lives, so you can predict the output before you read it. Another of the variable scope examples that shows the rule in output.
| # | Example | Rule demonstrated |
|---|---|---|
| 1 | Local hides global (shadowing) | Innermost declaration wins |
| 2 | Nested blocks and loop variables | Block scope ends at } |
| 3 | Static local counter versus automatic local | Lifetime is not scope |
| 4 | Local static used as a one-time init flag | Embedded idiom |
| 5 | Stack frames: the same local at the same address | Automatic storage |
| 6 | Returning the address of a local (dangling pointer) | Lifetime ends at return |
| 7 | static global: internal linkage across two files | File-private state |
| 8 | extern across two files, shared counter | External linkage |
| 9 | Scope ladder: one name, four meanings | Shadowing chain |
| 10 | Mini exercises | Self-test |
Example 1: A Local Hides a Global (Shadowing)
Problem: The same name level is declared three times. Which one does each printf use? Among the variable scope examples this is the most common in interviews.
-Wshadow. A shadowed variable compiles silently, so an assignment can land in the wrong object.Example 2: Nested Blocks and Loop Variables
Problem: A variable declared inside a loop body lives only inside it. Show both the working program and the error you get when you break the rule. These variable scope examples build on each other.
What the compiler says when you use a name outside its block
square was created inside the braces and destroyed at the closing brace. The compiler reports undeclared because, from the point of view of the line after the loop, the name does not exist. Fix: declare the variable in the outer block if you need it afterwards.
Example 3: A Static Local Counter Versus an Automatic Local
Problem: Two counters are incremented the same way. Why does only one of them remember its value?
Lifetime: entire program
Memory: .bss (SRAM), fixed address
Lifetime: one call
Memory: stack frame, released at return
static on a local.Example 4: A Static Local as a One-Time Initialization Flag
Problem: A driver function may be called from several places, but the hardware must be configured only once.
The flag has block scope, so no other function can accidentally clear it, yet it survives between calls. On the STM32F407 this variable sits in .bss and is zero (false) after reset, which is why the first call performs the setup. The pattern is not thread safe: with an RTOS, protect it with a mutex or initialize from one task.
Example 5: Stack Frames, One Slot Reused and One Frame per Recursion
Problem: Show that automatic variables of different calls can share the same address, while nested calls get new frames below the caller.
Absolute addresses are not printed because they differ between runs and platforms. The reproducible facts are that sequential calls reuse the freed space and that every nested call needs additional stack. On the STM32F407 the stack grows downward from the top of SRAM, so deep recursion eats the memory that sits below it and is dangerous with only 128 KB.
Example 6: Returning the Address of a Local (Dangling Pointer)
Problem: A function returns a pointer to its local variable. Does the compiler catch it, and how do you fix it?
GCC warns function returns address of local variable. Dereferencing such a pointer is undefined behaviour: the memory may already hold another function’s locals. In good() the variable is static, so its lifetime covers the whole program and the pointer stays valid. Other safe options are to let the caller pass in a buffer or to allocate statically.
Example 7: static at File Scope Gives Internal Linkage
Problem: Keep a counter private to one module. Only the module’s own functions may change it.
What happens when another file tries to reach it
Because s_count is static, the name is not exported to the linker, so main.c cannot link to it. This is encapsulation in plain C: the data is hidden behind counter_inc() and counter_get(), and you can change the representation later without touching callers.
Example 8: extern Across Two Files, One Shared Variable
Problem: An interrupt routine in one file counts events and the main loop in another file reads them. Both must use the same object.
main() must also be declared volatile, otherwise the optimiser may keep it in a register. This host demo calls the function normally, so volatile is not required here. Module 14 covers it in depth.| Linkage | How to write it | Visible to the linker? |
|---|---|---|
| External | File-scope int g_events; (plus extern elsewhere) | Yes |
| Internal | File-scope static int s_count; | No |
| None | Any local variable | No |
Example 9: The Scope Ladder, One Name With Four Meanings
Problem: The identifier x refers to four different objects in one file. Trace which is which, including the static inside the inner block that keeps counting across calls.
| Where | Object | Lifetime |
|---|---|---|
show() and main() | global x | whole program |
hide() outer | local x = 2 | one call |
hide() inner block | static x (3, 4, …) | whole program |
hide() after the block | local x = 2 again | one call |
Real projects should never rely on this. It is shown to make the lookup rule concrete: the compiler searches outward from the innermost block until it finds a declaration.
Example 10: Mini Exercises
Exercise 1: A function has static int n = 0; n++;. After 5 calls, what is n?
Exercise 2: Same code without static. After 5 calls?
Exercise 3: Can another file use a static int count; defined at file scope?
extern declaration elsewhere causes an undefined reference.Exercise 4: What warning flag finds a local that hides a global?
-Wshadow.Exercise 5: Is returning &local from a function ever correct?
static (or otherwise outlives the call).Exercise 6: Where is a static local stored on the STM32F407?
.data if it has a non-zero initializer, otherwise in .bss, both in SRAM. Never on the stack.Exercise 7: Which has bigger scope, a global or a static global?
Key Takeaways from the Variable Scope Examples
- The variable scope examples show that the innermost declaration always wins, and
-Wshadowreveals accidents. - Block scope ends at the closing brace; using the name afterwards is a compile error.
- A static local has block scope but program lifetime: it is the safe way to keep state private to one function.
- Never return the address of an automatic variable: GCC warns, and the behaviour is undefined.
- A file-scope
staticis private to its file; an ordinary global is shared throughextern. - Static locals and globals live in SRAM sections (
.data/.bss); automatic locals live on the stack.
Ready for the quiz?
Next: predict-the-output scope questions, code challenges and interview answers on scope and lifetime.
Need Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments