Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The register keyword in C is a storage class specifier that hints to the compiler that a local variable or function parameter should be stored directly in a CPU hardware register rather than in standard memory (RAM).
register int counter;

Compiler Behavior

The register keyword acts strictly as a non-binding optimization hint. Modern compilers utilize advanced register allocation algorithms (such as graph coloring) and routinely ignore the register specifier. If the compiler disregards the hint, it allocates the variable in memory (typically on the stack). However, the variable’s storage class strictly remains register at the C language level. This ensures that all semantic constraints associated with the keyword continue to apply, regardless of where the variable is physically stored. The C standard imposes no restrictions on the data type or size of a register variable. Declaring a large struct or array with register is perfectly valid C; the compiler will simply ignore the hint and allocate the oversized object in memory.

Scope and Lifetime

  • Scope: Block scope. register variables are only visible within the function or lexical block in which they are declared.
  • Lifetime: Automatic storage duration. The variable is allocated upon entering the block and deallocated upon exiting.

Syntactic and Semantic Constraints

1. The Address-of Operator (&) is Prohibited Because hardware registers do not reside in the memory space, they do not possess memory addresses. Applying the unary address-of operator (&) to a register variable results in a strict compile-time error (constraint violation). This rule is enforced at the language level, even if the compiler ignores the optimization hint and places the variable on the stack.
void compute(void) {
    register int val = 10;
    
    // int *ptr = &val; // COMPILE-TIME ERROR: Cannot take address of register variable
}
2. Array Decay and Undefined Behavior A critical consequence of the address-of prohibition affects arrays declared with the register specifier. In C, array evaluation typically involves decaying into a pointer to its first element, an operation that implicitly requires taking a memory address. Because this is forbidden for register variables, a register array cannot safely decay into a pointer. According to the C standard, if an array object has the register storage class and is used in an expression that triggers array decay—such as accessing elements via the subscript operator (arr[0])—the result is Undefined Behavior. While some compilers may choose to emit a diagnostic error, it is not mandated by the standard. A register array is safely restricted to being an operand of operators that do not trigger array decay, such as sizeof.
#include <stddef.h>

void process(void) {
    register int arr[5];
    
    size_t s = sizeof(arr); // VALID: Does not require array decay
    // arr[0] = 1;          // UNDEFINED BEHAVIOR: Array decay on a register object
}
3. Restriction on Storage Contexts The register specifier can only be applied to local variables and function parameters. It is illegal to declare global (file-scope) variables with the register storage class, and it cannot be combined with other storage class specifiers such as static or extern.
// register int global_var; // COMPILE-TIME ERROR: Illegal storage class for file-scope variable

void execute(register int param) { // VALID: Function parameter
    // static register int state;  // COMPILE-TIME ERROR: Conflicting storage specifiers
}
Master C with Deep Grasping Methodology!Learn More