The following qualifiers can be used in front of variables to give the compiler more information about the intended use of the variable and, in some cases, to help it generate better code.
1. The register Qualifier
If a function uses a particular variable heavily, you can request that access to the variable be made as fast as possible by the compiler. Typically, this means requesting that it be stored in one of the machine’s registers when the function is executed. This is done by prefixing the declaration of the variable by the keyword register, as follows:
register int index;
register char *textPtr;
Both local variables and formal parameters can be declared as register variables. The types of variables that can be assigned to registers vary among machines. The basic data types can usually be assigned to registers, as well as pointers to any data type.
Even if your compiler enables you to declare a variable as a register variable, it is still not guaranteed that it will do anything with that declaration. It is up to the compiler.
You might want to also note that you cannot apply the address operator to a register variable. Other than that, register variables behave just as ordinary automatic variables.
2. The volatile Qualifier
This is sort of the inverse to const. It tells the compiler explicitly that the specified vari- able will change its value. It’s included in the language to prevent the compiler from optimizing away seemingly redundant assignments to a variable, or repeated examination of a variable without its value seemingly changing. A good example is to consider an
I/O port. Suppose you have an output port that’s pointed to by a variable in your pro- gram called outPort. If you want to write two characters to the port, for example an O followed by an N, you might have the following code:
*outPort = ‘O’;
*outPort = ‘N’;
A smart compiler might notice two successive assignments to the same location and, because outPort isn’t being modified in between, simply remove the first assignment from the program. To prevent this from happening, you declare outPort to be a volatile pointer, as follows:
volatile char *outPort;
3. The restrict Qualifier
Like the register qualifier, restrict is an optimization hint for the compiler. As such, the compiler can choose to ignore it. It is used to tell the compiler that a particular pointer is the only reference (either indirect or direct) to the value it points to through- out its scope. That is, the same value is not referenced by any other pointer or variable within that scope.
int * restrict intPtrA;
int * restrict intPtrB;
tell the compiler that, for the duration of the scope in which intPtrA and intPtrB are defined, they will never access the same value. Their use for pointing to integers inside an array, for example, is mutually exclusive.
Source: Kochan Stephen G. (2004), Programming in C: A Complete Introduction to the C Programming Language, Sams; Subsequent edition.