Contents

Keywords in C

Introduction

Keywords like `static`, `const`, and `volatile` modify variable behavior in C. This document explains their use cases, advantages, disadvantages, and interactions.

1. The `static` Keyword

Definition:

`static` controls the scope and lifetime of variables/functions.

Types of Declarations:

1. Static Local Variables:

  • Retain value between function calls.
  • Stored in the data segment (not stack).
  • Scope: Local to the block.
  • Lifetime: Entire program execution.

Example:

#include <stdio.h>
void counter() {
    static int count = 0; // Preserved across calls
    count++;
    printf("Count: %d\n", count);
}
int main() {
    counter(); // Count: 1
    counter(); // Count: 2
    return 0;
}

2. Static Global Variables/Functions:

  • Scope limited to the file where declared.
  • Avoids naming conflicts in multi-file projects.

Example:

// File: utils.c
static int hidden = 10; // Only visible in this file

static void print_hidden() { // File-local function
    printf("%d\n", hidden);
}

Use Cases:

  • Preserve state between function calls (e.g., counters).
  • Encapsulate variables/functions within a file.

Advantages:

  • Prevents unintended external access.
  • Reduces namespace pollution.

Disadvantages:

  • Overuse increases memory usage (data segment).

2. The `const` Keyword

Definition:

`const` declares read-only variables. Attempts to modify them cause compiler errors.

Types of Declarations:

1. Constant Variables:

const int MAX = 100;
MAX = 200; // Error: Assignment to read-only variable

2. Pointers to Constants:

const int *ptr = &MAX;
*ptr = 200; // Error: Can't modify via ptr

3. Constant Pointers:

int x = 5;
int *const ptr = &x; // Pointer address is fixed
ptr = &y; // Error: Can't reassign ptr

Use Cases:

  • Define configuration values (e.g., buffer sizes).
  • Enforce immutability in function parameters.

Advantages:

  • Prevents accidental modification.
  • Improves code readability.

Disadvantages:

  • Can’t be used for runtime-initialized constants (requires `#define` or `enum`).

3. The `volatile` Keyword

Definition:

`volatile` tells the compiler that a variable’s value may change unexpectedly (e.g., hardware registers, ISRs).

Example (Without `volatile` Optimization):

int flag = 0;
while (flag == 0) {
    // Compiler may optimize this loop into "while(true)"
}

Example (With `volatile`):

volatile int flag = 0;
while (flag == 0) {
    // Compiler checks flag on every iteration
}

Use Cases:

  • Memory-mapped hardware registers.
  • Variables modified in interrupts or multithreaded code.

Advantages:

  • Ensures fresh reads from memory.
  • Disables dangerous compiler optimizations.

Disadvantages:

  • Reduces optimization opportunities.

4. Combined Keywords

1. `const + volatile`

Use Case:

  • A read-only hardware register (e.g., status register).
  • Value can change externally, but code shouldn’t write to it.

Example:

const volatile uint32_t *STATUS_REG = (uint32_t*)0x4000;
// Can’t modify STATUS_REG, but its value may change
uint32_t status = *STATUS_REG; // Read-only access

2. `static + volatile`

Use Case:

  • A variable shared between an ISR and a function, but scoped to a file.

Example:

static volatile bool data_ready = false;

void ISR() {
    data_ready = true; // Modified in ISR
}

void process_data() {
    while (!data_ready); // Wait in main code
    // Process data
}

3. `static + const`

Use Case:

  • A file-local constant (e.g., lookup table).

Example:

static const float PI = 3.14159; // File-scoped constant

Comparison Table

CombinationUse CaseExample
`static`Preserve state across callsCounters, file-local vars
`const`Immutable dataConfiguration constants
`volatile`Externally-modified variablesHardware registers
`const + volatile`Read-only hardware registersStatus registers
`static + volatile`Shared ISR-main thread variablesSensor flags

Key Takeaways

  • `static`: Control scope/lifetime.
  • `const`: Enforce immutability.
  • `volatile`: Disable optimizations for unstable variables.
  • Combine keywords for specialized use cases (e.g., `const volatile`).

Common Pitfalls

  • Forgetting `volatile` for variables modified in ISRs.
  • Using `const` with pointers incorrectly (e.g., `const int*` vs `int* const`).
  • Overusing `static` leading to higher memory usage.