---
title: 1.11 Variable Lifetime and Storage Duration
description: "The lifetime of an object is the period during program execution in which the object exists. C defines different storage durations that determine how long an object retains its storage. Scope and storage duration describe different properties. **Scope** determines *where*…"
url: "https://edcret.in/docs/c-programming/basic-refreshers/1-11-variable-lifetime-and-storage-duration/"
updated: "2026-09-06"
category: C Programming / Basic Refreshers
---

# 1.11 Variable Lifetime and Storage Duration

The lifetime of an object is the period during program execution in which the object exists. C defines different storage durations that determine how long an object retains its storage.

Scope and storage duration describe different properties. **Scope** determines *where* an identifier can be accessed in your code, while **storage duration** determines *how long* the associated object exists in memory.

## 1. Automatic and Static Storage Duration

The most common storage durations are automatic (local variables) and static (global or static local variables).

```
#include <stdio.h>

void counter()
{
    int automatic = 0;
    static int persistent = 0;

    automatic++;
    persistent++;

    printf("automatic = %d, persistent = %dn", automatic, persistent);
}

int main()
{
    counter();
    counter();
    counter();

    return 0;
}
```

**Example Output**

Plaintext

```
automatic = 1, persistent = 1
automatic = 1, persistent = 2
automatic = 1, persistent = 3
```

**Explanation**

- **`automatic` has automatic storage duration:** A new instance is created each time execution enters the function block, and its storage ends when execution leaves that block. Therefore, it is initialized to 0 on each call and becomes 1.
- **`persistent` is declared with `static`:** It has static storage duration. Its storage exists for the entire execution of the program, so its value is preserved between calls to `counter()`.

## 2. Allocated Storage Duration

Objects with allocated storage duration are created and destroyed dynamically at runtime. The programmer has complete, explicit control over their lifetime using memory management functions like `malloc()`, `calloc()`, and `free()` (requires `<stdlib.h>`).

```
#include <stdio.h>
#include <stdlib.h>

void create_allocated() {
    // 1. Allocation: The object's lifetime begins here.
    int* allocated_var = (int*)malloc(sizeof(int));

    if (allocated_var == NULL) {
        printf("Memory allocation failed!n");
        return;
    }

    *allocated_var = 100;
    printf("Allocated value: %dn", *allocated_var);

    // 2. Release: The object's lifetime ends here.
    free(allocated_var);
}

int main() {
    create_allocated();
    return 0;
}
```

**Example Output**

Plaintext

```
Allocated value: 100
```

**Explanation**

Unlike `automatic` variables that are destroyed automatically when a function finishes, `allocated_var` points to memory on the heap. Its lifetime strictly lasts from the moment `malloc()` is called until `free()` is called. Failing to call `free()` results in a memory leak.

## 3. Thread Storage Duration

Introduced in C11, objects with thread storage duration exist for the lifetime of a specific thread. If multiple threads run the same code, each thread gets its own separate, independent instance of the variable using the `thread_local` keyword (requires `<threads.h>`).

```
#include <stdio.h>
#include <threads.h>

// thread_local means EVERY thread gets its own isolated copy
thread_local int thread_counter = 0;

int thread_worker(void* arg) {
    int thread_id = *(int*)arg;

    // Increment the counter. It only affects this specific thread's copy.
    thread_counter++;
    thread_counter++;

    printf("Thread %d finished. thread_counter = %dn", thread_id, thread_counter);
    return 0;
}

int main() {
    thrd_t thread1, thread2;
    int id1 = 1, id2 = 2;

    // Create two parallel threads running the same function
    thrd_create(&thread1, thread_worker, &id1);
    thrd_create(&thread2, thread_worker, &id2);

    // Wait for both threads to finish
    thrd_join(thread1, NULL);
    thrd_join(thread2, NULL);

    return 0;
}
```

**Example Output**

Plaintext

```
Thread 1 finished. thread_counter = 2
Thread 2 finished. thread_counter = 2
```

**Explanation**

Even though both threads use the exact same variable name (`thread_counter`), they do not share the data. The storage for Thread 1's copy ends when Thread 1 terminates, and the same applies to Thread 2.

## Summary of Storage Durations

| **Storage Duration** | **Object Exists...** |
| --- | --- |
| **Automatic** | From entry into the associated block until execution leaves it. |
| **Static** | For the entire execution of the program. |
| **Allocated** | From manual allocation (`malloc`) until the storage is explicitly released (`free`). |
| **Thread** | For the lifetime of the specific thread it belongs to. |
