Learning Objectives
- Understand the concept of variable scope in C programming
- Differentiate between global and local variables
- Explore block scope and its implications
- Learn about static local variables and their persistence
- Apply scope rules in practical programming scenarios
What is Variable Scope?
Variable Scope refers to the region of the program where a variable can be accessed or used. It determines the visibility and lifetime of variables in different parts of your program.
Part 1: Global Variables
Global variables are declared outside all functions and can be accessed from any function within the program.
Example 1.1: Basic Global Variable Usage
// Global variable declaration int globalVar = 100; void displayGlobal() { printf("Global variable in displayGlobal(): %d\n", globalVar); } void modifyGlobal() { globalVar = 200; printf("Modified global variable: %d\n", globalVar); } int main() { printf("Initial global variable: %d\n", globalVar); displayGlobal(); modifyGlobal(); displayGlobal(); return 0; }
Expected Output:
Initial global variable: 100 Global variable in displayGlobal(): 100 Modified global variable: 200 Global variable in displayGlobal(): 200
- Global variables are accessible from all functions
- Changes made to global variables persist throughout the program
- Global variables are stored in the data segment of memory
Part 2: Local Variables vs Global Variables
Local variables are declared inside functions and have limited scope. Let's compare their behavior with global variables.
Example 2.1: Local Variable Scope
// Global variable int globalNumber = 50; void testLocalScope() { int localNumber = 25; // Local variable printf("Inside testLocalScope():\n"); printf(" Local variable: %d\n", localNumber); printf(" Global variable: %d\n", globalNumber); // Modifying both variables localNumber = 75; globalNumber = 150; printf("After modification:\n"); printf(" Local variable: %d\n", localNumber); printf(" Global variable: %d\n", globalNumber); } int main() { printf("In main() before function call:\n"); printf(" Global variable: %d\n", globalNumber); // This would cause an error - localNumber is not accessible here // printf("Local variable: %d\n", localNumber); // ERROR! testLocalScope(); printf("In main() after function call:\n"); printf(" Global variable: %d\n", globalNumber); return 0; }
Expected Output:
In main() before function call: Global variable: 50 Inside testLocalScope(): Local variable: 25 Global variable: 50 After modification: Local variable: 75 Global variable: 150 In main() after function call: Global variable: 150
Part 3: Block Scope Variables
Variables can also be declared within code blocks (enclosed by curly braces) and have block scope.
Example 3.1: Block Scope Demonstration
int main() { int outerVar = 10; printf("Outer variable: %d\n", outerVar); // Creating a new block { int innerVar = 20; // Block scope variable printf("Inside block:\n"); printf(" Inner variable: %d\n", innerVar); printf(" Outer variable: %d\n", outerVar); // Modifying outer variable from inner block outerVar = 30; printf(" Modified outer variable: %d\n", outerVar); } printf("Outside block:\n"); printf(" Outer variable: %d\n", outerVar); // This would cause an error - innerVar is not accessible here // printf("Inner variable: %d\n", innerVar); // ERROR! return 0; }
Expected Output:
Outer variable: 10 Inside block: Inner variable: 20 Outer variable: 10 Modified outer variable: 30 Outside block: Outer variable: 30
Example 3.2: Nested Block Scope
int main() { int level1 = 100; printf("Level 1 variable: %d\n", level1); { int level2 = 200; printf("Level 2 - level1: %d, level2: %d\n", level1, level2); { int level3 = 300; printf("Level 3 - level1: %d, level2: %d, level3: %d\n", level1, level2, level3); // All variables are accessible here level1 = 111; level2 = 222; level3 = 333; } printf("Back to Level 2 - level1: %d, level2: %d\n", level1, level2); // level3 is not accessible here } printf("Back to Level 1 - level1: %d\n", level1); // level2 and level3 are not accessible here return 0; }
Expected Output:
Level 1 variable: 100 Level 2 - level1: 100, level2: 200 Level 3 - level1: 100, level2: 200, level3: 300 Back to Level 2 - level1: 111, level2: 222 Back to Level 1 - level1: 111
Part 4: Static Local Variables
Static local variables retain their value between function calls, unlike regular local variables.
Example 4.1: Static vs Regular Local Variables
void demonstrateStatic() { int regularVar = 0; // Regular local variable static int staticVar = 0; // Static local variable printf("Regular variable: %d, Static variable: %d\n", regularVar, staticVar); regularVar++; staticVar++; printf("After increment - Regular: %d, Static: %d\n", regularVar, staticVar); } int main() { printf("First call to demonstrateStatic():\n"); demonstrateStatic(); printf("\nSecond call to demonstrateStatic():\n"); demonstrateStatic(); printf("\nThird call to demonstrateStatic():\n"); demonstrateStatic(); return 0; }
Expected Output:
First call to demonstrateStatic(): Regular variable: 0, Static variable: 0 After increment - Regular: 1, Static: 1 Second call to demonstrateStatic(): Regular variable: 0, Static variable: 1 After increment - Regular: 1, Static: 2 Third call to demonstrateStatic(): Regular variable: 0, Static variable: 2 After increment - Regular: 1, Static: 3
Example 4.2: Practical Use of Static Variables - Function Call Counter
int getCallCount() { static int callCount = 0; callCount++; return callCount; } void processData(int data) { int callNumber = getCallCount(); printf("Processing data %d (Call #%d)\n", data, callNumber); } int main() { processData(10); processData(20); processData(30); printf("Total function calls: %d\n", getCallCount()); return 0; }
Expected Output:
Processing data 10 (Call #1) Processing data 20 (Call #2) Processing data 30 (Call #3) Total function calls: 4
Variable Scope Summary
| Variable Type | Scope | Lifetime | Memory Location | Accessibility |
|---|---|---|---|---|
| Global | Entire program | Program execution | Data segment | All functions |
| Local | Function only | Function execution | Stack | Current function |
| Block | Block only | Block execution | Stack | Current block |
| Static Local | Function only | Program execution | Data segment | Current function |
Complete Lab Exercise
Try this comprehensive example that demonstrates all concepts:
#include <stdio.h> // Global variable int globalCounter = 0; void demonstrateAllScopes(int parameter) { // Local variable int localVar = 10; // Static local variable static int staticCounter = 0; printf("\n=== Function Call ===\n"); printf("Parameter: %d\n", parameter); printf("Local variable: %d\n", localVar); printf("Static counter: %d\n", staticCounter); printf("Global counter: %d\n", globalCounter); // Block scope demonstration { int blockVar = 50; printf("Block variable: %d\n", blockVar); // Modifying variables from different scopes localVar += 5; staticCounter++; globalCounter++; blockVar += 10; printf("After modification in block:\n"); printf(" Local: %d, Static: %d, Global: %d, Block: %d\n", localVar, staticCounter, globalCounter, blockVar); } printf("After block (blockVar not accessible):\n"); printf(" Local: %d, Static: %d, Global: %d\n", localVar, staticCounter, globalCounter); } int main() { printf("Variable Scope Demonstration\n"); printf("============================\n"); // Multiple function calls to observe behavior demonstrateAllScopes(100); demonstrateAllScopes(200); demonstrateAllScopes(300); printf("\n=== Final Global Counter Value ===\n"); printf("Global counter: %d\n", globalCounter); return 0; }
Expected Output:
Variable Scope Demonstration ============================ === Function Call === Parameter: 100 Local variable: 10 Static counter: 0 Global counter: 0 Block variable: 50 After modification in block: Local: 15, Static: 1, Global: 1, Block: 60 After block (blockVar not accessible): Local: 15, Static: 1, Global: 1 === Function Call === Parameter: 200 Local variable: 10 Static counter: 1 Global counter: 1 Block variable: 50 After modification in block: Local: 15, Static: 2, Global: 2, Block: 60 After block (blockVar not accessible): Local: 15, Static: 2, Global: 2 === Function Call === Parameter: 300 Local variable: 10 Static counter: 2 Global counter: 2 Block variable: 50 After modification in block: Local: 15, Static: 3, Global: 3, Block: 60 After block (blockVar not accessible): Local: 15, Static: 3, Global: 3 === Final Global Counter Value === Global counter: 3
Lab Assignment Questions
Exercise Questions:
- Analysis Question: Explain why the static counter increases with each function call while the local variable resets to 10.
- Prediction Question: What would happen if we declared a local variable with the same name as a global variable?
- Coding Challenge: Write a function that uses a static variable to calculate the running average of numbers passed to it.
- Error Analysis: Identify and explain the compilation errors in attempting to access block-scoped variables outside their blocks.
- Best Practices: When would you prefer static local variables over global variables?
Key Takeaways
- Global variables are accessible throughout the program but should be used sparingly
- Local variables provide encapsulation and are destroyed when the function exits
- Block scope allows for temporary variables within specific code sections
- Static local variables combine local accessibility with persistent storage
- Understanding scope helps prevent naming conflicts and memory management issues