• Aucun résultat trouvé

Type Qualifiers

Dans le document III CP·6 (Page 85-91)

Syntax:

type-qualifier:

const volatile Constraints:

Data Declarations

The same type qualifier may not appear more than once in the same specifier list or qualifier list, either directly or via one or more typedefs.

Semantics:

The properties associated with qualified types are meaningful only for expressions that are Ivalues.9

No attempt should be made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type. Nor should an attempt be made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type.] 0

An object that has volatile-qualified type is assumed to be modified in ways unknown to the compiler or have other unknown side effects.

If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type. The specification of a function type should not include any type qualifiers, since they are ignored.]]

For two qualified types to be compatible, both must 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.

Examples:

An object declared

extern const volatile int real_tiMe_clock;

may be modifiable by hardware, but cannot be assigned to, incremented, or decremented within this compilation unit.

The following declarations and expressions illustrate the behavior when type qualifiers modify an aggregate type:

9 CP-6 C often places a const object that is not volatile in a read-only region of storage.

10 This applies to those objects that behave as if they were defined with qualified types, even if they are never actually defined as objects in the program (such as an object at a memory-mapped input/output address).

11 Both of these can only occur through the use of typedefs.

HA17-00 Type Qualifiers 5-9

Data Declarations

direct-declarator [ con~tant-expressionopt

J

direct-declarator ( parameter- type-list ) direct-declarator ( identifier-listopt ) pointer:

declaration-specifiers abstract-declarator opt identifier-list:

identifier

identifier-li~t , identifier Semantics:

Data Declarations

Each declarator declares one identifier, and asserts that when an operand of the same form as the declarator appears in an expression, it designates a function or object with the scope, storage duration, and type indicated by the declaration specifiers.

In the following subsections, consider a declaration T Dl

where T contains the declaration specifiers that specify a type T (such as int) and Dl is a declarator that contains an identifier ident. The type specified for the identifier ident in the various forms of declarator is described inductively using this notation.

If, in the declaration "T Dl", Dl has the form identifier

then the type specified for ident is T.

If, in the declaration "T Dl", Dl has the form

( D )

then ident has the type specified by the declaration "T D" . Thus, a declarator in parentheses is identical to the unparenthesized declarator, but the binding of complex declarators may be altered by parentheses.

Pointer Declarators Semantics:

If, in the declaration "T Dl", Dl has the form

*

type-qualifier-listopt D

and the type specified for ident in the declaration "T D" is "derived-declarator-type-list T", then the type specified for ident is "derived-declarator-type-list type-qualifier-list pointer to

T". For each type qualifier in the list, ident is a so-qualified pointer.

For two pointer types to be compatible, both must be identically qualified and both must be pointers to compatible types.

HA17-00 Pointer Declarators 5-11

Data Declarations Examples:

The following pair of declarations demonstrates the difference between a "variable pointer to a constant value" and a "constant pointer to a yariable yalue":

const int *ptr_to_constant;

int *const constant_ptr;

The contents of an object pointed to by ptr_ to_constant may not be modified through that pointer, but ptr _to_constant itself may be changed to point to another object.

Similarly, the contents of the int pointed to by constant_ptr may be modified, but constant_ptr itself always points to the same location.

The declaration of the constant pointer constant _ptr may be clarified by including a definition for the type "pointer to int":

typedef int *int_ptr;

const int_ptr constant_ptr;

declares constant_ptr as an object that has type "const-qualified pointer to int".

Array Declarators Constraints:

The expression delimited by [ and] (which specifies the size of an array) is an integral constant expression that has a value greater than zero.

Semantics:

If, in the declaration "T Dl", Dl has the form D [constant- ezpressionopt ]

and the type specified for ident in the declaration "T D" is "derived-declarator-type-list T", then the type specified for ident is "derived-declarator-type-list array of T" .12 If the size is not present, the array type is an incomplete type.

For two array types to be compatible, both must have compatible element types, and if both size specifiers are present, they must have the same value.

Examples:

float fa[ll] , *afp[17];

declares an array of float numbers and an array of pointers to float numbers.

Note the distinction between the declarations:

extern int *x;

extern int y [] ;

The first declares x to be a pointer to int; the second declares y to be an array of int of unspecified size (an incomplete type), the storage for which is defined elsewhere.

12 When several "array of" specifications are adjacent, a multidimensional array is declared.

5-12 Array Declarators HA17-00

Data Declarations Function Declarators (including Prototypes)

Constraints:

A function declarator may not specify a return type that is a function type or an array type.

The only storage-class specifier that may occur in a parameter declaration is register.

An identifier list in a function declarator that is not part of a function definition must be empty.

Semantics:

If, in the declaration "T Dl", Dl has the form D (parameter-type-list)

or

D (identifier-listopt )

and the type specified for ident in the declaration "T D" is "derived-declarator-type-list T", then the type specified for ident is "derived-declarator-type-list function returning T".

A parameter type list specifies the types of, and may declare identifiers for, the parameters of the function. If the list terminates with an ellipsis (, ... ), no information about the number or types of the parameters after the comma is supplied.13The special case of void as the only item in the list specifies that the function has no parameters.

In a parameter declaration, a single typedef name in parentheses is taken to be an abstract declarator that specifies a function with a single parameter, not as redundant parentheses around the identifier for a declarator.

The storage-class specifier in the declaration specifiers for a parameter declaration, if present, is ignored unless the declared parameter is one of the members of the parameter type list for a function definition.

An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a function definition specifies that the function has no parameters. The empty list in a function declarator that is not part of a function definition specifies that no information about the number or types of the parameters is supplied.

For two function types to be compatible, both must specify compatible return types.14The parameter type lists, if both are present, must agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters must have compatible types. If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the

13 The macros defined in the <stdarg .h> header (Section 15) may be used to access arguments that correspond to the ellipsis.

14 If both function types are "old style", parameter types are not compared.

HA17-00 Function Declarators (including Prototypes) 5-13

Data Declarations

parameter list cannot have an ellipsis terminator, and the type of each parameter must be compatible 'with the type that results from the application of the default argument promotions. If one type has a parameter type list and the other type is specified by a function definition that contains a (possibly empty) identifier list, both must agree in the number of parameters, and the type of each prototype parameter must be compatible with the type that results from the application of the default argument promotions to the type of the corresponding identifier. (For each parameter declared with function or array type, its type for these comparisons is the one that results from conversion to a pointer type, as in Section 7, External Data Definitions. For each parameter declared with qualified type, its type for these comparisons is the unqualified version of its declared type.)

Examples:

The declaration

int f(void), *fip(), (*pfi)();

declares a function f with no parameters returning an int, a function fip with no parameter specification returning a pointer to an int, and a pointer pfi to a function with no parameter specification returning an into It is especially useful to compare the last two. The binding of *fip() is *(fip(», so that the declaration suggests, and the same construction in an expression requires, the calling of a function fip, and then using indirection through the pointer result to yield an into In the declarator (*pfi) (), the extra parentheses are necessary to indicate that indirection through a pointer to a function yields a function designator which is then used to call the function; it returns an into If the declaration occurs outside of any function, the identifiers have file scope and external linkage. If the declaration occurs inside a function, the identifiers of the functions f and fip have block scope and either internal or external linkage (depending on what file scope declarations for these identifiers are visible), and the identifier of the pointer pfi has block scope and no linkage.

Here are two more intricate examples:

int (*apfi[3])(int *x, int *y);

declares an array apfi of three pointers to functions returning into Each of these functions has two parameters that are pointers to into The identifiers x and yare declared for descriptive purposes only and go out of scope at the end of the declaration of apfi. The declaration

int (*fpfi(int (*) (long) , int»(int, ... );

declares a function fpfi that returns a pointer to a function returning an into The function fpfi has two parameters: a pointer to a function returning an int (with one parameter of type long), and an into The pointer returned by fpfi points to a function that has one int parameter and accepts zero or more additional arguments of any type.

5-14 Function Declarators (including Prototypes) HA17-00

Data Declarations

Dans le document III CP·6 (Page 85-91)