7.1 Overview

Declarators are the components of a declaration that specify names. Declarators can also modify basic type information to cause names to be functions or pointers to objects or functions. (Specifiers, discussed in Chapter 6, convey properties such as type and storage class. Modifiers, discussed in this chapter and in Appendix B, modify declarators.) Figure 7.1 shows a complete declaration of two names, szBuf and strcpy, and calls out the components of the declaration.

Microsoft Specific

Most Microsoft extended keywords can be used as modifiers to form derived types; they are not specifiers or declarators. (See Appendix B, “Microsoft-Specific Modifiers.”)¨Syntax

declarator:
dname
ptr-operator declarator
declarator
(argument-declaration-list)cv-mod-list
declarator
[constant-expressionopt]
(declarator )

ptr-operator:
*cv-qualifier-listopt
&cv-qualifier-listopt
complete-class-name:: *cv-qualifier-listopt

cv-qualifier-list:
cv-qualifier cv-qualifier-listopt

cv-qualifier:
const
volatile

cv-mod-list:
cv-qualifier cv-mod-listopt
pmodel cv-mod-listopt

pmodel: one of
__near
__far
__huge

dname:
name
class-name
~class-name
typedef-name
qualified-type-name

Declarators appear in the declaration syntax after an optional list of specifiers (decl-specifiers). These specifiers are discussed in Chapter 6, “Declarations.” A declaration can contain more than one declarator, but each declarator declares only one name. The following sample declaration shows how specifiers and declarators are combined to form a complete declaration:

const char *pch, ch;

In the above declaration, the keywords const and char make up the list of specifiers. Two declarators are listed: *pch, and ch. The simplified syntax of a declaration, then, is the following, where const char is the type, and *pch and ch are the identifiers:

type identifier1[[, identifier2[[...,identifiern]]]] ;

When the binding of elements in a complicated declarator does not yield the desired result, you can use parentheses for clarification. A better technique, however, is to use a typedef or a combination of parentheses and typedefs. Consider declaring an array of pointers to functions. Each function must obey the same protocol so that the arguments and return values are known:

// Function returning type int that takes one

// argument of type char *.

typedef int (*PIFN)( char * );

// Declare an array of 7 pointers to functions

// returning int and taking one argument of type

// char *.

PIFN pifnDispatchArray[7];

The equivalent declaration can be written without typedefs, but it is so complicated that the potential for error exceeds any benefits:

int ( *pifnDispatchArray[7] )( char * );