Declarators [ HP C/iX Reference Manual ] MPE/iX 5.0 Documentation
HP C/iX Reference Manual
Declarators
A declarator introduces an identifier and specifies its type, storage
class, and scope.
Syntax
declarator ::=
[pointer] direct-declarator
direct-declarator ::=
identifier
(declarator)
direct-declarator [[constant-expression]]
direct-declarator (parameter-type-list)
direct-declarator ([identifier-list])
pointer ::=
* [type-qualifier-list]
* [type-qualifier-list] pointer
type-qualifier-list ::=
type-qualifier
type-qualifier-list type-qualifier
parameter-type-list ::=
parameter-list
parameter-list , ...
parameter-list ::=
parameter-declaration
parameter-list , parameter-declaration
parameter-declaration ::=
declaration-specifiers declarator
declaration-specifiers [abstract-declarator]
identifier-list ::=
identifier
identifier-list , identifier
Description
Various special symbols may accompany declarators. Parentheses change
operator precedence or specify functions. The asterisk specifies a
pointer. Square brackets indicate an array. The constant-expression
specifies the size of an array.
A declarator specifies one identifier and may supply additional type
information. When a construction with the same form as the declarator
appears in an expression, it yields an entity of the indicated scope,
storage class, and type.
If an identifier appears by itself as a declarator, it has the type
indicated by the type specifiers heading the declaration.
Declarator operators have the same precedence and associativity as
operators appearing in expressions. Function declarators and array
declarators bind more tightly than pointer declarators. You can change
the binding of declarator operators using parentheses. For example,
int *x[10];
is an array of 10 pointers to ints. This is because the array declarator
binds more tightly than the pointer declarator. The declaration
int (*x)[10];
is a single pointer to an array of 10 ints. The binding order is altered
with the use of parentheses.
Pointer Declarators
If D is a declarator, and T is some combination of type specifiers and
storage class specifiers (such as int), then the declaration T *D
declares D to be a pointer to type T. D can be any general declarator of
arbitrary complexity. For example, if D were declared as a pointer
already, the use of a second asterisk indicates that D is a pointer to a
pointer to T.
Some examples:
int *pi; /* pi: Pointer to an int */
int **ppi; /* ppi: Pointer to a pointer to an int */
int *ap[10]; /* ap: Array of 10 pointers to ints */
int (*pa)[10]; /* pa: Pointer to array of 10 ints */
int *fp(); /* fp: Function returning pointer to int */
int (*pf)(); /* pf: Pointer to function returning an int */
The binding of * (pointer) declarators is of lower precedence than either
[ ] (array) or () (function) declarators. For this reason, parentheses
are required in the declarations of pa and pf.
Array Declarators
If D is a declarator, and T is some combination of type specifiers and
storage class specifiers (such as int), then the declaration
T D[constant-expression];
declares D to be an array of type T.
You declare multidimensional arrays by specifying additional array
declarators. For example, a 3 by 5 array of integers is declared as
follows:
int x[3][5];
This notation (correctly) suggests that multidimensional arrays in C are
actually arrays of arrays. Note that the [ ] operator groups from left
to right. The declarator x[3][5] is actually the same as ((x[3])[5]).
This indicates that x is an array of three elements each of which is an
array of five elements. This is known as row-major array storage.
You can omit the constant-expression giving the size of an array under
certain circumstances. You can omit the first dimension of an array (the
dimension that binds most tightly with the identifier) in the following
cases:
* If the array is a formal parameter in a function definition.
* If the array declaration contains an initializer.
* If the array declaration has external linkage and the definition
(in another translation unit) that actually allocates storage
provides the dimension.
Following are examples of array declarations:
int x[10]; /* x: Array of 10 integers */
float y[10][20]; /* y: Matrix of 10x20 floats */
extern int z[ ]; /* z: External integer array of undefined */
/* dimension */
int a[ ]={2,7,5,9}; /* a: Array of 4 integers */
int m[ ][3]= { /* m: Matrix of 2x3 integers */
{1,2,7},
{6,6,6} };
Note that an array of type T that is the formal parameter in a function
definition has been converted to a pointer to type T. The array name in
this case is a modifiable lvalue and can appear as the left operand of an
assignment operator. The following function will clear an array of
integers to all zeros. Note that the array name, which is a parameter,
must be a modifiable lvalue to be the operand of the ++ operator.
void clear(a, n)
int a[]; /* has been converted to int * */
int n; /* number of array elements to clear */
{
while(n--) /* for the entire array */
*a++ = 0; /* clear each element to zero */
}
Function Declarators
If D is a declarator, and T is some combination of type specifiers and
storage class specifiers (such as int), then the declaration
T D (parameter-type-list)
or
T D ([identifier-list])
declares D to be a function returning type T. A function can return any
type of object except an array or a function. However, functions can
return pointers to functions or arrays.
If the function declarator uses the form with the parameter-type-list, it
is said to be in "prototype" form. The 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 of types of the parameters after the comma is supplied.
The special case of void as the only item in the list specifies that the
function has no parameters.
If a function declarator is not part of a function definition, the
optional identifier-list must be empty.
Function declarators using prototype form are only allowed in ANSI mode.
Functions can also return structures. If a function returns a structure
as a result, the called function copies the resulting structure into
storage space allocated in the calling function. The length of time
required to do the copy is directly related to the size of the structure.
If pointers to structures are returned, the execution time is greatly
reduced. (But beware of returning a pointer to an auto struct--the
struct will disappear after returning from the function in which it is
declared.)
The function declarator is of equal precedence with the array declarator.
The declarators group from left to right. The following are examples of
function declarators:
int f(); /* f: Function returning an int */
int *fp(); /* fp: Function returning pointer to an int */
int (*pf)(); /* pf: Pointer to function returning an int */
int (*apf[])(); /* apf: Array of pointers to functions */
/* returning int */
Note that the parentheses alter the binding order in the declarations of
pf and apf in the above examples.
MPE/iX 5.0 Documentation