A function pointer is a pointer to a function. A pointer refers to a function whose return value is a pointer. However, the following questions are still confusing. Can you give me more details?
(1) float (** def) [10] What is def?
(2) double * (* gh) [10] what is gh?
(3) What is double (* f [10]) () f?
(4) int * (* B) [10]) What is B? It seems a little messy. Do you have any tips to remember and understand it clearly?
======================================
Answer:
(1) def is a pointer, pointing to the object is also a pointer, pointing to the pointer eventually pointing to an array consisting of 10 float.
(2) gh is a pointer pointing to an array consisting of 10 elements, and the array element is a pointer of the double * type.
(3) f is an array composed of 10 elements. Each element is a pointer and the pointer points to a function. The function type is non-parameter and the return value is double. the example of the tips below is similar to this one.
(4) B is a pointer pointing to an array consisting of 10 elements. The array element is an int * type pointer.
TIPS:
How can we resolve a complex type declaration? For example:
Char (* a [3]) (int );
Why is a declared? Pointer? Array? Or a function?
During analysis, it starts from the nearest (by operator priority) of. We can see that the closest sign of a is [] -- Note: * has a lower priority. Since [] exists after a, a is an array and an array containing three elements.
What is the type of each element in this array? Although array a only contains three elements: a [0], a [1], and a [2], a [3] has actually crossed the border, however, when analyzing the element type of array a, we need the formal element a [3]. Once we know the type of a [3], we know the type of the elements of. What type is a [3? Is a pointer, because it is preceded by *. From this we can see that the element of array a is a pointer.
Pointer is not enough. For a pointer, you must specify the type of the pointer. If it points to something, you can see what a [3] is (a [3] is a pointer, and it points to something * a [3. Continue to observe by priority. We can see that * a [3] is followed by parentheses, so we can be sure that * a [3] is a function. That is, the element of array a is a pointer to the function.
What type of function is pointed? This is obviously a function of the int type and char type.
Now the resolution is complete.
According to the above method, you can parse the complicated ones step by step.
Just like Xi Wu is not trying to beat people but to guard ourselves, we understand that the above method is to understand the complicated statements written by others, rather than to construct such complicated stuff by ourselves in practice. When complex declarations are required, you can use typedef instead. For example, the preceding statement can be changed to two sentences:
Typedef char (* FUN_PTR) (int );
FUN_PTR a [3];
This is much clearer.
In addition, the above analysis method makes the nature of some things clearer. For example, an n-dimensional array is essentially a one-dimensional array. Let's look at a specific example:
Int a [3] [5];
This statement declares a one-dimensional array containing three elements, each of which is an array consisting of five int numbers. We cannot understand that a is a one-dimensional array containing five elements, and each element is an array consisting of three int numbers. Why? Or use the above method for analysis.
In some books or on the Internet, the "look to the right, look to the left" method is actually not universal, for example, it is not applicable to the analysis of the essence of multi-dimensional arrays. this method masks the essence. in essence, it should be based on what we have mentioned above and separated layer by layer based on the operator priority.
========================================================== ==============================================
I. pointer Functions
When a function declares that its return value is a pointer, it actually returns an address to the called function to be used in an expression that requires a pointer or address.
Format:
Type specifier * function name (parameter)
Of course, because an address is returned, the type specifiers are generally int.
Example: int * GetDate ();
Int * aaa (int, int );
The function returns an address value, which is often used on an element address of the returned array.
Copy codeThe Code is as follows:
Int * GetDate (int wk, int dy );
Main ()
{
Int wk, dy;
Do
{
Printf (Enter week (1-5) day (1-7)/n );
Scanf (% d, & wk, & dy );
}
While (wk <1 | wk> 5 | dy <1 | dy> 7 );
Printf (% d/n, * GetDate (wk, dy ));
}
Int * GetDate (int wk, int dy)
{
Static int calendar [5] [7] =
{
{1, 2, 3, 4, 5, 6, 7 },
{8, 9, 10, 11, 12, 13, 14 },
{15,16, 17,18, 19,20, 21 },
{22, 23, 24, 25, 26, 27, 28 },
{29,30, 31,-1}
};
Return & calendar [wk-1] [DY-1];
}
The program should be well understood. The subfunction returns the address of an element in the array. The output is the value in this address.
Ii. function pointer
The pointer to a function contains the address of the function, which can be used to call the function. The Declaration format is as follows:
Type specifier (* function name) (parameter)
In fact, it cannot be called the function name. It should be called the variable name of the pointer. This special Pointer Points to a function that returns an integer value. The pointer Declaration must be consistent with the declaration that it points to the function.
Parentheses outside the pointer and pointer operators change the default operator priority. Without parentheses, it becomes a prototype declaration of a function that returns an integer pointer.
For example:
Void (* fptr )();
Assign the function address to the function pointer in the following two forms:
Fptr = & Function;
Fptr = Function;
It is not necessary to use the address operator, because a Function Identifier represents its address. If it is a function call, it must also contain a parameter table enclosed in parentheses.
You can use the following two methods to call a function through a pointer:
X = (* fptr )();
X = fptr ();
The second format looks like a function call. However, some programmers tend to use the first format because it explicitly states that the function is called through pointers rather than function names. The following is an example:
Copy codeThe Code is as follows:
Void (* funcp )();
Void FileFunc (), EditFunc ();
Main ()
{
Funcp = FileFunc;
(* Funcp )();
Funcp = EditFunc;
(* Funcp )();
}
Void FileFunc ()
{
Printf ("FileFunc/n ");
}
Void EditFunc ()
{
Printf ("EditFunc/n ");
}
Program output:
FileFunc
EditFunc
3. pointer
The pointer seems confusing. Their declaration has two asterisks. For example:
Char ** cp;
If there are three asterisks, It is the pointer of the pointer, the four asterisks are the pointer of the pointer, and so on.
When you are familiar with simple examples, you can cope with complex situations. Of course, in the actual program, only the second-level pointer is used. The three asterisks are not common, let alone the four asterisks.
The pointer must use the pointer address.
Char c = 'a ';
Char * p = & c;
Char ** cp = & p;
The pointer can not only access the pointer it points to, but also access the data pointed to by the pointer it points. The following are several examples:
Char * p1 = * cp; // (& c)
Char c1 = ** cp;
You may want to know how this structure works? The pointer allows the called function to modify local pointer variables and process pointer arrays.
Copy codeThe Code is as follows:
Void FindCredit (int **);
Main ()
{
Int vals [] = {, 5,-, 0 };
Int * fp = vals;
FindCredit (& fp );
Printf (% d/n, * fp );
}
Void FindCredit (int ** fpp)
{
While (** fpp! = 0)
If (** fpp <0) break;
Else (* fpp) ++;
}
First, use an array address to initialize the pointer fp, and then pass the pointer address as a real parameter to the FindCredit () function (). The FindCredit () function indirectly obtains the data in the array through the expression ** fpp.
To traverse the array to find a negative value, the FindCredit () function performs auto-increment operations on the object that the caller points to the array instead of its own pointer to the caller pointer. The statement (* fpp) ++ is used to perform auto-increment operations on the pointer pointed to by the form parameter pointer. However, because the * operator is higher than the ++ operator, parentheses are required here. If no parentheses exist, the ++ operator applies to the double pointer fpp.
4. pointer to the pointer Array
Another method of pointer is to process the pointer array. Some programmers prefer to use pointer arrays instead of multi-dimensional arrays. A common usage is to process strings.
Copy codeThe Code is as follows:
Char * Names [] =
{
Bill,
Sam,
Jim,
Paul,
Charles,
0
};
Main ()
{
Char ** nm = Names;
While (* nm! = 0) printf (% s/n, * nm ++ );
}
First, initialize the pointer nm with the address of the struct pointer array Names. Each call to printf () first passes the attention pointer pointed to by the pointer nm, and then carries out an auto-increment operation on the nm so that it points to the next element (or pointer) of the array ). Note that the preceding syntax is * nm ++. It first obtains the content pointed to by the pointer and then auto-increment the pointer.
Note that the last element in the array is initialized to 0, and the while loop is used to determine whether it is at the end of the array. Pointers with zero values are often used as terminator for loop arrays. The programmer calls the zero-value pointer a NULL pointer ). The NULL pointer is used as the Terminator. When adding or deleting elements to the tree type, you do not need to modify the code for traversing the array, because the array still ends with a null pointer.