Data Type Qualifiers

Qualifier Description
const Explicitly declares a data object as a data item that cannot be changed. Its value is set at initialization. You cannot use const data objects in expressions requiring a modifiable lvalue. For example, a const data object cannot appear on the left-hand side of an assignment statement.
volatile Maintains consistency of memory access to data objects. It tells the compiler that the variable should always contain its current value even when optimized, so that the variable can be queried when an exception occurs. Volatile objects are read from memory each time their value is needed, and written back to memory each time they are changed.

The volatile qualifier is useful for data objects having values that may be changed in ways unknown to your program (such as the system clock). Portions of an expression that reference volatile objects are not to be changed or removed.

Note: These type qualifiers are only meaningful in expressions that are lvalues.

For a volatile or const pointer, you must put the keyword between the * and the identifier. For example:

int * volatile x;     /* x is a volatile pointer to an int */
int * const y = &z;   /* y is a const pointer to the int variable z */

For a pointer to a volatile or const data object, the type specifier, qualifier, and storage class specifier can be in any order. For example:

volatile int *x1;     /* x1 is a pointer to a volatile int  */
int volatile *x2;     /* x2 is a pointer to a volatile int  */
const int *y1;        /* y1 is a pointer to a const int  */
int const *y2;        /* y2 is a pointer to a const int  */

In the following example, the pointer to y is a constant. You can change the value that y points to, but you cannot change the value of y:

int * const y

In the following example, the value that y points to is a constant integer and cannot be changed. However, you can change the value of y:

const int * y

For other types of volatile and const variables, the position of the keyword within the definition (or declaration) is less important. For example:

volatile struct omega {
                         int limit;
                         char code;
                      } group;

provides the same storage as:

struct omega {
                int limit;
                char code;
             } volatile group;

In both examples above, only the structure variable group receives the volatile qualifier. Similarly, if you specified the const keyword instead of volatile, only the structure variable group receives the const qualifier. The const and volatile qualifiers when applied to a structure or union also apply to the members of the structure or union.

Although enumeration, structure, and union variables can receive the volatile or const qualifier, enumeration, structure, and union tags do not carry the volatile or const qualifier. For example, the blue structure does not carry the volatile qualifier:

volatile struct whale {
                           int weight;
                           char name[8];
                      } beluga;
struct whale blue;

The keywords volatile and const cannot separate the keywords enum, struct, and union from their tags.

You cannot declare or define a volatile or const function but you can define or declare a function that returns a pointer to a volatile or const object.

You can put more than one qualifier on a declaration but you cannot specify the same qualifier more than once on a declaration.

If you put a type definition in the same declaration as a definition of a variable having the volatile or const qualifier, the qualifier applies to that variable only. For example:

enum shape { round, square, triangular, oblong } volatile object;
enum shape appearance;

The variable object is defined as volatile. The variable appearance does not have the volatile qualifier. Similarly, if you specified the const keyword instead of volatile, only the variable object receives the const qualifier.