Join WhatsApp

Join Now

Join Telegram

Join Now

“When Variables Wear Masks: Static vs Dynamic Scoping Told with Code and Coffee”

By Sagar Miraje

Published On:

Follow Us

“Sir, if I define a variable with the same name inside a function, will it overwrite the one from the main?” 

I paused mid sip of my chai. This wasn’t the first time a student had asked that. But this time, the look on Ayan’s face part curiosity, part rebellion told me we were heading into a fun rabbit hole. 

That day’s topic? Variable scoping. Not loops. Not arrays. Not even pointers. Just good ol’ scoping. The silent architect of control, the invisible force behind who sees what, when. 

Scene 1: A Stack of Books, A Stack of Functions 

Before I even say “static” or “dynamic”, I usually take my students on a detour straight to the world of stack memory. 

“You know how books stack?” I ask. “You place one, then another on top. Want the bottom one? Tough luck you have to remove the ones above first. That’s your call stack in a C program.” 

I remember sketching three rectangles on the whiteboard that day: 

| fun3 | 
| fun2 | 
| fun1 | 
| main | 
 

Each box was a function call a memory box created when the function was invoked. And inside each? Its own local variables. I called them activation records, just like I learned during compiler design lectures in grad school. But I told my students to imagine them as mini rooms each function lives in its own room with its own cupboards (variables). No room peeks into another unless you pass them a key (parameter). 

And this was the hook: Which variable value gets used when two rooms have cupboards labeled with the same name? 

That’s where scoping walks in. 

Scene 2: The Tale of Two Scopes 

“C uses static scoping,” I say. 

“But what does that mean?” asks Kiran, who always wants the TL;DR first. 

So, I tell them a story. 

The Tale of the Lost Glasses 

Imagine your mother yells: “The glasses are on the table!” 

Now, where do you look? 

In your house, of course. 

Now imagine you’re visiting a friend’s house. You get a call: “The glasses are on the table!” 

Would you look in your friend’s kitchen? No. You know the person meant your house, because that’s where the instruction was written. 

This is static scoping. The search for variables begins not from where the function is called, but from where it is defined. 

Static Scoping: A Concrete Example 

Let’s say: 

int a = 5; 
 
void fun() { 
   printf(“%d”, a); 

 
int main() { 
   int a = 10; 
   fun(); 
   return 0; 

 

Now I ask: “What gets printed?” 

Ten hands go up, “10!” 

I smile. “Wrong.” 

The answer is 5. 

Gasps. 

“But main has a = 10!” they protest. 

“True,” I say. “But fun() is defined outside main. When fun() looks for a, it checks where it was defined, not where it was called. That’s static scoping. The outer a shadows your local one because fun() doesn’t even know main’s a exists.” 

Let’s Simulate Dynamic Scoping 

Now I introduce a parallel universe a language with dynamic scoping. 

Imagine the same code. But in this alternate world, variable resolution depends on where the function was called. So when fun() is called from main, it inherits main’s variable bindings. 

I write a pseudo dynamic version: 

int a = 5; 
 
void fun() { 
   printf(“%d”, a); // would print 10 in dynamic world 

 
int main() { 
   int a = 10; 
   fun(); // dynamic scoping uses this a 
   return 0; 

 

Now, students are intrigued. “So it’s like… fun() reads the caller’s glasses, not its own?” 

“Exactly!” I say. 

Dynamic scoping is like calling someone for directions and assuming they’re in your city not theirs. 

Why C Chooses Static Scoping 

We then explore why C chooses static scoping. It boils down to predictability and efficiency. 

Since everything is resolved at compile time, the compiler can figure out where a variable comes from by looking at the code structure. No need to track the call history at runtime. It’s like using Google Maps with GPS vs. asking every passerby for directions. Static scoping is clean, safe, and fast. 

But more importantly it enables modular programming. 

When I write: 

void display() { 
   int x = 10; 
   printf(“%d”, x); 

 

I know x means the one defined inside display() not something floating in main() or some caller. 

That’s peace of mind. 

When Students Simulate Dynamic Scoping 

I give students a mini challenge. I tell them to fake dynamic scoping in C. The trick? Use global variables to simulate call time scope. 

int a = 5; 
 
void fun() { 
   printf(“%d”, a); 

 
int main() { 
   a = 10; 
   fun(); // prints 10 
   return 0; 

 

Now, fun() uses the modified value of a as if it were dynamically scoped. 

“Not elegant,” I admit. “But it shows what dynamic scoping feels like.” 

We reflect: dynamic scoping makes debugging harder. One rogue caller can mess up the entire context. It’s like asking someone to find a book, but changing the label names behind their back. 

Nested Functions & the Illusion of Scope 

Now comes the cool part. I ask: “Can you define a function inside another in C?” 

“Nope,” they say. 

But I say: “Imagine if you could.” 

So I sketch this on the board (just a simulation):  

void outer() { 
   int a = 100; 
 
   void inner() { 
       printf(“%d”, a); // access a from outer 
   } 
 
   inner(); 

 

“In this fantasy,” I say, “inner has access to a from outer, because of static scoping. If this were dynamic, and someone else called inner(), it might pick up a different a entirely.” 

This imaginary exercise really hammers in the concept. 

When Static Scoping Saves the Day 

I recall a real bug from a student project. Sahil had a count variable in main, and another one in a logging function. 

He was confused: “Why is my count printing zero again and again?” 

Turned out, he had declared int count = 0; inside the logger function, shadowing the global count. 

Once he understood scoping, he laughed: “So they’re two different ‘rooms’ and my logging guy has his own counter!” 

Exactly. 

Closing Thoughts: Scoping Is the Lens 

In the end, I tell students this: 

“Scoping is how your program sees. It’s the lens through which your functions view the world.” 

Static scoping gives each function its own secure lens no interference, no unexpected hijacks. 

Dynamic scoping is more like using someone else’s glasses sometimes it works, but often it leads to blurry messes. 

In C, your variable’s scope is fixed at compile time what you see is where it was written. And thank heavens for that. 

Is C statically scoped or dynamically scoped? 

C is statically scoped. Variables are resolved based on where functions and variables are written, not where they are called. 

Can we simulate dynamic scoping in C? 

Not directly, but you can mimic its behavior using global variables, which get picked up at call time rather than definition time. 

Why doesn’t C allow nested functions? 

Nested functions complicate things like scope resolution and stack memory management. C opts for simplicity and static structure. 

What is an activation record? 

An activation record is the memory chunk created for a function call. It stores local variables, parameters, and the return address. 

How can I avoid scope related bugs? 

Use distinct variable names for different scopes. Avoid shadowing. And understand where your variable is defined and who can see it. 

I am Sagar Miraje, a Computer Science graduate with a Bachelor of Technology and 7 years of experience as a C language programming developer. I specialize in writing efficient, low-level code for systems programming, embedded applications, and performance-critical software. My strength lies in optimizing memory usage, handling pointers, and working close to the hardware to deliver fast and reliable solutions. Over the years, I’ve contributed to core system modules, debugged complex runtime issues, and collaborated with cross-functional engineering teams. I’m passionate about problem-solving and always eager to push the limits of what C programming can achieve.

Leave a Comment