HOWTO · C
The register Keyword in C
Learn how the register storage-class specifier works in C, including declarations, address restrictions, pointers, and scope.
On this page
In C versions that support it, register is a storage-class specifier traditionally used to suggest that an object may benefit from fast access. It does not guarantee storage in a CPU register or make a program faster. The compiler decides how to implement the object, and the rules described below can depend on the C standard targeted by your compiler.
Overview of the register Keyword in C
The register specifier reflects an older optimization model: programmers could mark frequently accessed objects as candidates for register storage. Modern compilers make optimization decisions from the program and target platform, so adding the specifier is not a performance promise. Use it only when your target C version supports it and when its language rules fit the declaration; measure performance separately if that is your goal.
A CPU has a limited set of registers, but C does not require ordinary objects to be loaded into a register before each operation. The compiler may keep values in registers, memory, or other locations as it translates and optimizes the program. Source code cannot rely on a particular physical location. If a compiler warns that register is obsolete or unsupported under the selected language mode, check that compiler’s documentation and the C version configured for the project.
Using the register Keyword in C
The following complete program uses register with three local objects and prints their values. It is a runnable example, but its output is not shown here.
#include <stdio.h>
int main(void) {
register char letter = 'S';
register double amount = 10.0;
register int count = 8;
printf("letter: %c\n", letter);
printf("amount: %.1f\n", amount);
printf("count: %d\n", count);
return 0;
}
The declaration syntax is otherwise familiar: place register among the declaration specifiers before the type and identifier. The example uses fixed values so you can focus on the declaration and the formatted output. Whether the compiler honors the historical storage suggestion is an implementation decision, and the program’s correctness must not depend on that choice.
Getting the Address of a register Variable in C
In C versions that define the register storage-class specifier, the address operator & cannot be applied to an object declared with register. This restriction applies even if an implementation happens to keep the object’s value in memory. It is a language constraint, rather than a statement about whether a physical register has an address.
For example, the declaration register int item = 22; is valid in a compatible language mode, but int *address = &item; violates the constraint. A compiler must diagnose a constraint violation, though the wording, severity, and formatting of its diagnostic are implementation-specific. Do not copy a diagnostic from another compiler as if it were guaranteed output.
Using register with a Pointer Variable in C
A pointer object can itself use register in C versions that support the specifier. The pointer can still store the address of a different object; the restriction is on taking the address of the pointer object itself. For example, int value = 15; followed by register int *cursor = &value; lets cursor point to value, and *cursor accesses that pointed-to integer.
This distinction is useful when reading code: &value obtains the address of the ordinary value object, while &cursor would attempt to obtain the address of the register pointer object and is not permitted by the same constraint. The specifier does not change what a pointer points to or guarantee where either object is stored. Check the target language mode if the compiler rejects the declaration or reports the specifier as unsupported.
Using register with Other Storage-Class Specifiers in C
register is itself a storage-class specifier, so it cannot be combined with another storage-class specifier for the same declaration. In particular, declarations such as auto register int value;, static register int value;, and extern register int value; are not valid combinations in language modes that support register.
A compiler diagnoses an invalid combination, but its message is not standardized as a fixed string. For a valid declaration, choose the one storage-class specifier that matches the intended lifetime and linkage rules. The type (int in these examples) and qualifiers are separate parts of a declaration; they do not make two storage-class specifiers compatible.
Scope of register Variables in C
The specifier is for block-scope objects and function parameters in C versions that support it; it is not permitted for a file-scope object. A function parameter may be written, for example, as int total(register int count). Within a function body, a block-scope declaration such as register int count = 22; is another permitted form. A file-scope declaration such as register int count; violates the applicable constraint and requires a diagnostic.
“Local variable” is therefore an incomplete description: it can obscure the permitted function-parameter case. Scope and storage duration are related concepts, but they are not interchangeable. The register specifier does not promise that an object lives in a CPU register, and its presence does not make the object visible outside its ordinary scope. When maintaining older code, verify the project’s selected C version and compiler mode before relying on these declarations.