Distinguish function pointers and pointer functions _

Source: Internet
Author: User

About the pointer and the group to chop constantly the confusion of the grievances is really said a lot, but now should have been cleared. With the foundation of the previous lecture, the content of this lecture is relatively easy to understand.

1. Pointer to function (function pointer)

To analyze such a declaration, void (*F) (); Although the precedence of () is higher than *, but because of the existence of parentheses, the first thing to do is to dereference, so f is a pointer; next executes (), indicating that f points to a function that does not return any values. Now come to the conclusion that F is a pointer to a function that does not take a parameter and returns no value, for short, a function pointer (pointer to function).

Compare int (*p) [100],p is a pointer to an array containing 100 integral elements, they have a common feature: the Pointer declarator (*) and the identifier (f or P) are limited to one parenthesis, since the parentheses are the highest priority, so we start from the identifier from the inside out of the analysis, You can get the results above.

<1>. Initialization

Note that a pointer to a function (a function pointer) points to a function rather than a normal variable, and it points to a function that has a specific type, and that the type of the function is determined by its return value type and formal parameter list, regardless of the function name. You can use function names or function pointers of the same type function when initializing a function pointer (and, of course, 0 pointer constants). If there is a function void Test (), int wrong_match (int) and function pointer Void (*PTF) ().

The following initialization is wrong because the type of the function pointer does not match the type of the function:

f = wrong_match;

f = & Wrong_match;

PTF = Wrong_match;

PTF = & Wrong_match;

The following initialization and assignment are legal:

f = test;

f = &test;

PTF = test;

PTF = &test;

f = PF;

The explanation is that both test and &test can be used to initialize the function pointer. The C language specifies that the function name will be converted to a pointer to the function, unless the function name is used as the operand of the & operator or the sizeof operator (note: the operand of the function name for sizeof is illegal). that is, F = test, the test is automatically converted to &test, and f= &test; has been shown to use &test, so the test will no longer be converted. So referencing the function name directly is equivalent to applying the & operator to the function name, and both methods get pointers to the function.

<2>. Calling a function from a function pointer

There are two ways to call a function through a function pointer, either by using the function pointer directly or by using the dereference operator before the function pointer, as follows:

f = test;

PTF = test;

f ();

(*f) ( ); The parentheses on both sides of the pointer are very important, which means that the reference to F is first, and then the corresponding function is called

PTF ();

(*PTF) ( ); Brackets are also not less

All of the above statements can achieve the function of calling test. The ANSI C Standard considers F () as a shorthand for (*f) (), and it is recommended to use the form F () because it is more consistent with the logic of function calls. Note: If a pointer to a function is not initialized, or has a 0 Value (0 pointer constant), the pointer cannot be used in a function call. A function can be safely invoked only if the pointer has been initialized or is assigned to a function.

<3>. Inquiry function name

Now there are the following procedures:

#include <stdio.h>

Voidtest ()

{

printf ("Test called!/n");

}

int main ()

{

void (*f) ();

f = test;

f ();

(*f) ( );

test++; error, standard disables self-increment of pointers to functions

Test = Test + 2; error, cannot assign a value to the function name, nor can it be used for arithmetic operations

printf ("%p/n", test);

printf ("%p/n", &test);

printf ("%p/n", *test);

return 0;

}

The results on my machine are as follows:

Test called!

Test called!

004013EE

004013EE

004013EE

The more difficult to understand in this program is that 3 output statements can be used to get the entry address of a function. First look at the function name test, which is similar to the array name (note: Just like), is a symbol used to identify a function of the entry address, in the use of the function name will be converted to a pointer to the function, the value of the pointer is the function's entry address, &test said before: show the address of the GET function. For *test, it can be thought that because test has been converted to a function pointer, so *test is the function name pointed to by the pointer, and according to the function name will be converted to the function of the rules of the pointer, this function is also transformed into a pointer, so * Test is finally a pointer to the function test. For them, the%p format item output will get the entry address of the function test in 16 decimal notation. Note that the address of the function is unknown at compile time, but is determined at link time.

2. Functions that return pointers (pointer functions)

An array of analog pointers (remember), it will be easier to understand pointer functions. The so-called pointer function, is the function that returns the pointer, the function can return no value, can return an integer value, a real value, a character value, of course, can also return pointer value. Declaration of a pointer function: int *f (int i, int j); Recall the declaration of the pointer array: char *CARS[10]; the same is written in the form of understanding (non-industry practice) int* F (int i, int j); So it is very clear that because () the priority is higher than *, so the F is first combined with (), So f is a function that has two int parameters and returns a pointer to int type.

Many of the C-language library functions are pointer functions, such as string processing functions, and some function prototypes are given below:

Char *strcat (char *dest, const char *SRC);

Char *strcpy (char *dest, const char *SRC);

Char *strchr (const char *s, int c);

Char *strstr (const char *SRC, const char*sub);

Note that the return value of a function is not limited to a pointer to a variable, or a pointer to a function. It may be a bit painful to have a declaration of this function at first, but the practice two or three times should be understandable and mastered. First look at this statement: Int (*function (int)) (Double*,char); To understand the meaning of this declaration, first look at function (int), the function is declared as an argument, it has a formal parameter of type int, the return value of this function is a pointer, is exactly the function pointer that we will start to speak Int (*) (double*, char); This pointer points to a function that returns an int with two parameters, respectively, double* and char types. If you use TypeDef, you can simplify this declaration:

typedef int (*PTF) (double*, char);

PTF function (int);

To illustrate, for typedef int (*PTF) (Double*,char); Be careful not to use a # define thinking to see the TypeDef, if you use the "# define" thinking will Think (*PTF) (double*, char) is an int alias, but such an alias does not seem to be a legitimate name, so will be in a state of confusion. In fact, the above statement defines PTF as an alias for the type of function pointer, and the function pointer type int (*) (double*, char); equivalence, which means that PTF is now a type.

3. Mixed use of function pointers and pointer functions

A function pointer can be used not only as a return value type, but also as a function parameter, and if the formal and return values of a function are function pointers, the declaration looks more complex, for example:

void (*signal (int sig, Void (*func) (Intsiga))) (int siga); it looks really annoying, let's take a step-by-step analysis. Now the analysis is signal, because next to signal is the highest priority bracket, first with the parentheses, so the signal is a function, the parentheses are signal two parameters, an int type, a pointer to the function. Next, from the left, * represents a pointer to an object, where it is positioned to indicate that it is a return value type of signal, and can now remove the parsed signal as a whole, resulting in void (*) (int siga), very clear. is also a function pointer, which, like the second argument type in the signal parameter list, is a pointer to a function that takes an int type parameter and does not return any value. In the same way, a typedef can simplify this statement:

typedef void (*P_SIG) (int);

P_sig signal (int sig, P_sig func);

This signal function is a C language library function, defined in the signal.h, used to deal with the signal generated in the system, is a function commonly used in unix/linux programming, so here to explain it alone.

4. Array of function pointers

There is also a more common use of function pointers-an array of function pointers. Suppose you now have a file handler that selects the appropriate action via a menu button (open the file, read the file, write the file, close the file). These operations are implemented as functions and are of the same type, respectively:

void Open ();

void read ();

void Write ();

void Close ();

Now define a function pointer type alias pf:typedefvoid (*PF) (); Put the above 4 operation address into an array, get:

PF file_options[] = {

&open,

&read,

&write,

&close

};

The elements in this array are pointers to functions that do not accept parameters and do not return any values, so this is an array of function pointers. Next, define a pointer to the function pointer type action and initialize the first element of the array of function pointers: pf* action = file_options; if not, you can compare int ia[4] = {0, 1, 2, 3}; int *ip = IA; here pf equals int, so you should compare understood. Any of the operations in the array can be called by the subscript action on the pointer action, such as: Action[2] () calls the write operation, and so on. In practice, the pointer action can be associated with a mouse or other GUI object to achieve the appropriate purpose.

5. About complex declarations of pointers

The function pointer array in the 4th is declared with a TypeDef, which is the method to be advocated because it is more readable. If you do not use TypeDef, then the analysis will be more complex, the result is void (*file_options[]), the C language Complex declaration I do not want to talk too much, because in the actual use of the opportunity is not much, and recommend that you use TypeDef to simplify the complexity of the statement. There is an extremely effective method for analyzing complex declarations-the right-left law. The right-hand rule is roughly described as: A variable name that has never been defined begins reading a declaration, looks to the right, and then looks left. When the parentheses are encountered, the direction of reading is reversed. All content inside the parentheses is parsed out and the parentheses are popped out. This continues until the entire statement has been parsed. To analyze an example: int * (* (*FP) (int)) [10];

Read the steps:

1. Variable names that have never been defined start reading--------------------------------------------FP

2. Look to the right, there is nothing, encountered), so left to see, encountered a *------A pointer to an object

3. Jump out of parentheses, encounter (int)-----------------------------------a function with an int argument

4. Look left, find a *---------------------------------------(function) returns a pointer to an object

5. Jump out of brackets, look right, encounter [ten]------------------------------an array of 10 elements

6. Look left, find a *---------------------------------------a pointer to an object

7. Look to the left and find int-----------------------------------------int type

So FP is a pointer to a function that returns a pointer to an array that has 10 elements of type int*.

I do not have more examples of this, the following gives some statements, interested friends can try to analyze, the answer I will give in the next lecture:

1. int * (* (*a[5]) ()) ();

2. void * (*B) (char, int (*) ());

3. Float (* (*c[10]) (int*)) [5];

4. Int (* (*d) [2][3]) [4][5];

5. Int (* (* (*e) (int*)) [[]] (int*);

6. Int (* (*f[4][5][6]) (int*)) [10];

7. int * (* (* (*G) ()) [10]) ();

Distinguish function pointers and pointer functions _

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.