6.7.3 Type qualifiers
Syntax
type-qualifier:
const
restrict
volatile
Constraints
Types other than pointer types derived from object or incomplete types shall not be restrict-qualified.
Semantics
The properties associated with qualified types are meaningful only for expressions that are lvalues.[1]
If the same qualifier appears more than once in the same specifier-qualifier-list, either directly or via one or more typedefs, the behavior is the same as if it appeared only once.
If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.[2]
An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3. Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously.[3] What constitutes an access to an object that has volatile-qualified type is implementation-defined.
An object that is accessed through a restrict-qualified pointer has a special association with that pointer. This association, defined in 6.7.3.1 below, requires that all accesses to that object use, directly or indirectly, the value of that particular pointer.[4] The intended use of the restrict qualifier (like the register storage class) is to promote optimization, and deleting all instances of the qualifier from all preprocessing translation units composing a conforming program does not change its meaning (i.e., observable behavior).
If the specification of an array type includes any type qualifiers, the element type is so- qualified, not the array type. If the specification of a function type includes any type qualifiers, the behavior is undefined.[5]
For two qualified types to be compatible, both shall have the identically qualified version of a compatible type; the order of type qualifiers within a list of specifiers or qualifiers does not affect the specified type.
EXAMPLE 1
An object declared
extern const volatile int real_time_clock;
may be modifiable by hardware, but cannot be assigned to, incremented, or decremented.
EXAMPLE 2
The following declarations and expressions illustrate the behavior when type qualifiers modify an aggregate type:
const struct s { int mem; } cs = { 1 };
struct s ncs; // the object ncs is modifiable
typedef int A[2][3];
const A a = {{4, 5, 6}, {7, 8, 9}}; // array of array of const int
int *pi;
const int *pci;
ncs = cs; // valid
cs = ncs; // violates modifiable lvalue constraint for =
pi = &ncs.mem; // valid
pi = &cs.mem; // violates type constraints for =
pci = &cs.mem; // valid
pi = a[0]; // invalid: a[0] has type "const int *''
Footnotes