C Scope & Lifetime

Understanding variable visibility and memory duration

🎯 What are Scope & Lifetime?

Scope determines where variables can be accessed, while lifetime determines how long variables exist in memory.


#include <stdio.h>

int global_var = 100;  // Global scope

int main() {
    int local_var = 50;  // Local scope
    
    printf("Global: %d\n", global_var);
    printf("Local: %d\n", local_var);
    
    return 0;
}
                                    

Output:

Global: 100
Local: 50

Types of Scope

🌍

Global Scope

Accessible throughout the program

int global_count = 0;
// Accessible everywhere
🏠

Local Scope

Accessible within function only

void func() {
    int local_var = 10;
    // Only in this function
}
📦

Block Scope

Accessible within code block only

if (condition) {
    int block_var = 5;
    // Only in this block
}
⚙️

Function Scope

Labels have function scope

void func() {
    start:  // Function scope
    // goto start;
}

🔹 Global vs Local Scope

Variable scope determines where variables can be accessed within your program's code structure. Global variables declared outside functions are accessible everywhere, while local variables declared inside functions are restricted to that function. Global scope enables data sharing but reduces encapsulation, while local scope prevents naming conflicts and improves code maintainability. Proper scope management creates cleaner, more modular programs with better organization and reduced coupling.

#include <stdio.h>

int global_counter = 0;  // Global scope

void increment() {
    int local_step = 1;  // Local scope
    global_counter += local_step;
    printf("Inside function - Global: %d, Local: %d\n", global_counter, local_step);
}

int main() {
    int local_main = 10;  // Local to main
    
    printf("Before function call - Global: %d\n", global_counter);
    
    increment();
    increment();
    
    printf("After function calls - Global: %d, Local main: %d\n", global_counter, local_main);
    
    // local_step is not accessible here - would cause error
    // printf("%d", local_step);  // ERROR!
    
    return 0;
}

Output:

Before function call - Global: 0
Inside function - Global: 1, Local: 1
Inside function - Global: 2, Local: 1
After function calls - Global: 2, Local main: 10

🔹 Block Scope Example

Variables declared inside code blocks like loops and conditional statements have limited scope to that block. A variable declared inside an if statement exists only within that if block and becomes inaccessible outside. This block-level scoping prevents variable pollution and naming conflicts. Understanding block scope helps write cleaner code with predictable variable lifetimes and clearer variable relationships. Variables cease to exist when their block execution ends.

#include <stdio.h>

int main() {
    int outer_var = 100;
    
    printf("Outer variable: %d\n", outer_var);
    
    if (outer_var > 50) {
        int inner_var = 200;  // Block scope
        outer_var = 150;      // Modifying outer variable
        
        printf("Inside if block:\n");
        printf("  Outer: %d\n", outer_var);
        printf("  Inner: %d\n", inner_var);
        
        {
            int nested_var = 300;  // Nested block scope
            printf("  Nested block: %d\n", nested_var);
        }
        // nested_var not accessible here
    }
    
    printf("After if block:\n");
    printf("  Outer: %d\n", outer_var);
    // inner_var not accessible here - would cause error
    
    return 0;
}

Output:

Outer variable: 100
Inside if block:
  Outer: 150
  Inner: 200
  Nested block: 300
After if block:
  Outer: 150

🔹 Variable Lifetime

Variable lifetime represents how long variables exist in memory from creation to destruction during program execution. Local variables exist from declaration until their containing function returns, while global variables exist for the program's entire duration. Static variables retain values between function calls, extending their effective lifetime. Understanding variable lifetimes enables efficient memory management, prevents accessing freed memory, and clarifies program behavior during execution.

#include <stdio.h>

int global_lifetime = 1;  // Exists for entire program

void demonstrate_lifetime() {
    static int static_var = 0;  // Exists for entire program
    int auto_var = 0;           // Exists only during function call
    
    static_var++;
    auto_var++;
    
    printf("Static variable: %d\n", static_var);
    printf("Auto variable: %d\n", auto_var);
}

int main() {
    printf("Global at start: %d\n", global_lifetime);
    
    printf("\nFirst function call:\n");
    demonstrate_lifetime();
    
    printf("\nSecond function call:\n");
    demonstrate_lifetime();
    
    printf("\nThird function call:\n");
    demonstrate_lifetime();
    
    global_lifetime = 999;
    printf("\nGlobal at end: %d\n", global_lifetime);
    
    return 0;
}

Output:

Global at start: 1

First function call:
Static variable: 1
Auto variable: 1

Second function call:
Static variable: 2
Auto variable: 1

Third function call:
Static variable: 3
Auto variable: 1

Global at end: 999

🧠 Test Your Knowledge

Which variable type retains its value between function calls?