HPlogo HP C/HP-UX Reference Manual: Version A.05.55.02 > Chapter 3 Data Types and Declarations

Type Qualifiers

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

Syntax

   type-qualifier :: =
      const
      volatile
      __restrict (or restrict for C99)

Description

This section describes the type qualifiersvolatile, const and __restrict (or restrict for C99).

The volatile type qualifier directs the compiler not to perform certain optimizations on an object because that object can have its value altered in ways beyond the control of the compiler.

Specifically, when an object's declaration includes the volatile type qualifier, optimizations that would delay any references to (or modifications of) the object will not occur across sequence points. A sequence point is a point in the execution process when the evaluation of an expression is complete, and all side-effects of previous evaluations have occurred.

The volatile type qualifier is useful for controlling access to memory-mapped device registers, as well as for providing reliable access to memory locations used by asynchronous processes.

The const type qualifier informs the compiler that the object will not be modified, thereby increasing the optimization opportunities available to the compiler.

An assignment cannot be made to a constant pointer, but an assignment can be made to the object to which it points. An assignment can be made to a pointer to constant data, but not to the object to which it points. In the case of a constant pointer to constant data, an assignment cannot be made to either the pointer, or the object to which it points.

Type qualifiers may be used alone (as the sole declaration-specifier), or in conjunction with type specifiers, including struct, union,
enum,
and typedef. Type qualifiers may also be used in conjunction with storage-class specifiers.

Use the __restrict type qualifier on the declaration of a pointer type to indicate that the pointer is subject to compiler optimizations. The restrict is a C99 keyword which only supported under C99 mode.

The formal definition of restricted pointer in C99 follows:

  1. Let D be a declaration of an ordinary identifier that provides a means of designating an object P as a restrict-qualified pointer to type T.

  2. If D appears inside a block and does not have storage class extern, let B denote the block. If D appears in the list of parameter declarations of a function definition, let B denote the associated block. Otherwise, let B denote the block of main (or the block of the function that is called at program startup in a freestanding environment).

  3. In what follows, a pointer expression E is said to be based on object P if (at some sequence point in the execution of B prior to the evaluation of E) modifying P to point to a copy of the array object into which it formerly pointed would change the value of E. Note that based is defined only for expressions with pointer types.

  4. During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply:

    • T shall not be const-qualified.

    • Every other lvalue used to access the value of X shall also have its address based on P.

    • Every access that modifies X shall be considered also to modify P, for the purposes of this subclause.

    If P is assigned the value of a pointer expression E that is based on another restricted pointer object P2, associated with block B2, then either the execution of B2 shall begin before the execution of B, or the execution of B2 shall end prior to the assignment. If these requirements are not met, then the behavior is undefined.

  5. Here an execution of B means that portion of the execution of the program that would correspond to the lifetime of an object with scalar type and automatic storage duration associated with B.

  6. A translator is free to ignore any or all aliasing implications of uses of restrict.

Table 3-2 illustrates various declarations using the const and volatile type qualifiers.

Table 3-2 Declarations using const and volatile

Declaration

Meaning

volatile int vol_int;

Declares a volatile int variable.

const int *ptr_to_const_int;

int const *ptr_to_const_int;

Both declare a variable pointer to a constant int.

int *const const_ptr_to_int

Declares a constant pointer to a variable int.

int *volatile vpi, *pi;

Declares two pointers: vpi is a volatile pointer to an int; pi is a pointer to an int.

int const *volatile vpci;

Declares a volatile pointer to a constant int.

const *pci;

Declares a pointer to a constant int. Since no type specifier was given, it defaults to int.

 

When a type qualifier is used with a variable typed by a typedef name, the qualifier is applied without regard to the contents of the typedef. For example:

typedef int *t_ptr_to_int;
volatile t_ptr_to_int vol_ptr_to_int;

In the example above, the type of vol_ptr_to_int is volatile
t_ptr_to_int
, which becomes volatile pointer to int. If the type t_ptr_to_int were substituted directly in the declaration,

volatile int * ptr_to_vol_int;

the type would be pointer to volatile int.

Type qualifiers apply to objects, not to types. For example:

typedef int * t;
const t *volatile p;

In the example above, p is a volatile pointer to a const pointer to int. volatile applies to the object p, while const applies to the object pointed to by p. The declaration of p can also be written as follows:

t const *volatile p;

If an aggregate variable such as a structure is declared volatile, all members of the aggregate are also volatile.

If a pointer to a volatile object is converted to a pointer to a non-volatile type, and the object is referenced by the converted pointer, the behavior is undefined.

© Hewlett-Packard Development Company, L.P.