Aug. 25, 2010, 1:32 a.m.
posted by nogood
Item 17. Dealing with Function and Array DeclaratorsThe main confusion with pointer to function and pointer to array declarations arises because the function and array modifiers have higher precedence than the pointer modifier, so parentheses are often required. int *f1(); // function that returns int * int (*fp1)(); // ptr to function that returns int The same problem obtains with the high-precedence array modifier: const int N = 12; int *a1[N]; // array of N int * int (*ap1)[N]; // ptr to array of N ints Of course, once one can have a pointer to a function or to an array, one can have a pointer to such a pointer: int (**ap2)[N]; // ptr to ptr to array of N ints int *(*ap3)[N]; // ptr to array of N int * int (**const fp2)() = 0; // const ptr to ptr to func int *(*fp3)(); // ptr to func that returns int * Note that both the argument and return types contribute to the type of a function or function pointer.
char *(*fp4)(int,int);
char *(*fp5)(short,short) = 0;
fp4 = fp5; // error! type mismatch
Things can become immeasurably more complex when function and array modifiers appear in the same declaration. Consider the following common, incorrect attempt to declare an array of function pointers:
int (*)()afp1[N]; // syntax error!
In the (erroneous) declaration above, the appearance of the function modifier () signaled the end of the declaration, and the appended name afp1 signaled the start of a syntax error. It's analogous to writing an array declaration
int[N] a2; // syntax error!
that works just fine in Java but is not legal C++. The correct declaration of an array of function pointers puts the name being declared in the same location that it appears in a simple pointer to function. Then we say we want an array of those things: int (*afp2[N])(); // array of N ptr to func that returns int Things are starting to get unwieldy here, so it's time to reach for typedef. typedef int (*FP)(); // ptr to func that returns int FP afp3[N]; // array of N FP, same type as afp2 The use of typedef to simplify the syntax of complex declarations is a sign of caring for those poor maintainers who come after you. Using typedef, even the declaration of the standard set_new_handler function becomes simple: typedef void (*new_handler)(); new_handler set_new_handler( new_handler ); So, a new_handler (see Function Pointers [14, 49]) is a pointer to a function that takes no argument and returns void, and set_new_handler is a function that takes a new_handler as an argument and returns a new_handler as a result. Simple. If you try it without typedef, your popularity with those who maintain your code will plummet:
void (*set_new_handler(void (*)()))(); // correct, but evil
It's also possible to declare a reference to a function. int aFunc( double ); // func int (&rFunc)(double) = aFunc; // ref to func References to functions are rarely used and fill pretty much the same niche as constant pointers to functions: int (*const pFunc)(double) = aFunc; // const ptr to func References to arrays do provide some additional capability not provided by pointers to arrays and are discussed in Array Formal Arguments [6, 17]. |
- Comment