Pointer to another pointer
I. pointer concept:
As early as in the second part of this series, I have elaborated on the essence of pointers. Today, we need to learn a pointer that points to another pointer address. Let's review the pointer concept first!
When weProgramThe variables are as follows:
Short IntI;
CharA;
Short Int* PI;
The program will open up space for each variable in an address space in the memory, as shown in.
Memory Address → 6 7 8 9 10 11 12 13 14 15
-------------------------------------------------------------------------------------
... |
-------------------------------------------------------------------------------------
| Short int I | char a | short int * PI |
As shown in the figure, we can see:
The I variable occupies two bytes at the memory address 5.
A variable occupies one byte at the location of memory address 7.
The PI variable occupies two bytes at the memory address 9. (Note: PI is a pointer. Here, the pointer width is only two bytes, and the 32-bit system is four bytes)
Next, assign values as follows:
I =50;
Pi = & I;
After the assignment in the preceding two sentences, the memory image of the variable is as follows:
Memory Address → 6 7 8 9 10 11 12 13 14 15
--------------------------------------------------------------------------------------
... | 50 | 6 |
--------------------------------------------------------------------------------------
| Short int I | char a | short int * PI |
No: the PI value of the Short integer pointer variable is 6, which is the memory start address of the I variable. Therefore, when we perform read/write operations on * Pi, it is actually a read/write operation on the I variable. For example:
* Pi = 5; // It is equivalent to I = 5;
You can go back to the second article in this series for more detailed explanations.
2. pointer address and pointer pointing to another pointer address
In the previous section, we can see that the pointer variable itself is also in a memory address like other variables, for example, the memory start address of PI is 10. similarly, we may also point a pointer to this address.
See the following:Code:
Short Int** PPI;//This is a pointer to the pointer. Note that there are two * numbers.
PPI = π
First sentence: Short int ** PPI; -- declares a pointer variable PPI, which is used to store (or point to) the address of a short int * type pointer variable.
The second sentence: & PI refers to the PI address, and the PPI = π refers to assigning the PI address to the PPI. The address value 10 is assigned to the PPI. For example:
Memory Address → 6 7 8 9 10 11 12 13 14 15
------------------------------------------------------------------------------------
... | 50 | 6 | 10 |
------------------------------------------------------------------------------------
| Short int I | char a | short int * PI | short int ** PPI |
It can be seen that the starting address of the pointer variable PI is the content of the pointer variable PPI. So ......
What is the PPI value? -- 10.
* What is the PPI value? -- 6, that is, the value of pi.
** What is the PPI value? -- 50, that is, the value of I, is also the value of * pi.
Haha! I don't need to say too much. I believe you should understand this pointer!
3. One application instance
1. Design a function: void find1 (char array [], char search, char * PI)
Requirement: the array in this function parameter is a string ending with a 0 value. It is required that the character in the string array be the character in the search parameter. If found, the function returns the address of the first character found in the array string through the third parameter (PA. If not found, PA is 0.
DESIGN: The implementation code is as follows:
VoidFind1 (CharArray [],CharSearch,Char* PA)
{
IntI;
For(I =0; * (Array + I )! =0; I ++)
{
If(* (Array + I) = SEARCH)
{
Pa = array + I
Break;
}
Else If(* (Array + I) =0)
{
Pa =0;
Break;
}
}
}
Do you think this function can implement the required functions?
Debugging:
Let me call this function.
Void Main ()
{
Char STR [] = {"afsdfsdfdf \ 0 "}; // String to be searched
Char A = 'D '; // Set the characters to be searched
Char * P = 0 ; // If the pointer P points to the address of the first character found in the string.
Find1 (STR, A, P ); // Call a function to implement the operation.
If ( 0 = P)
{
Printf ("not found! \ N "); // 1. Output this sentence if not found
}
Else
{
Printf ("found, P = % d", P ); // Output this sentence if it is found.
}
}
Analysis:
What do you think is the output of the above Code?
Run it.
Alas! The output is: not found!
Instead of: found ,.......
Clearly, the value is 'D', and the fourth character of the STR string is 'D'. You can find it!
Let's look at the function definition: void find1 (char [] array, char search, char * pA)
Check the call: find1 (STR, A, P );
According to the analysis method in Article 5, an implicit value assignment operation is performed on each parameter during function calling.
The entire call is as follows:
Array = STR;
Search =;
Pa = P;//Note: the preceding sentence is an implicit action.
IntI;
For(I =0; * (Array + I )! =0; I ++)
{
If(* (Array + I) = SEARCH)
{
Pa = array + I
Break;
}
Else If(* (Array + I) =0)
{
Pa =0;
Break;
}
}
Oh! There is no difference between the parameter PA and the parameter search. It is a value transfer (Note: Address Transfer is actually an address value transfer )! Therefore, changing the PA value (of course an address value) does not change the P value of the real variable, therefore, the value of P is not changed (that is, the point of P is not changed ).
(If you have any questions, take a look at Article 5: Passing function parameters .)
Fixed:
Void find2 (char [] array, char search, char ** PPA)
{
Int I;
For (I = 0; * (array + I )! = 0; I ++)
{
If (* (array + I) = SEARCH)
{
* PPA = array + I
Break;
}
Else if (* (array + I) = 0)
{
* PPA = 0;
Break;
}
}
}
The main function is called as follows:
Find2 (STR, A, & P); // call a function to perform the operation.
Further analysis:
In this way, the entire operation is changed to the following:
Array = STR;
Search =;
PPA = & P; // Note: The above three statements are the Action implied during the call.
Int I;
For (I = 0; * (array + I )! = 0; I ++)
{
If (* (array + I) = SEARCH)
{
* PPA = array + I
Break;
}
Else if (* (array + I) = 0)
{
* PPA = 0;
Break;
}
}
Do you understand?
The PPA points to the IP address of the pointer p.
The modification to * PPA is the modification to the P value.
Debug it on your own.
The modified program can complete the required functions.
After understanding this example, we have achieved the purpose required in this article.
Function name and function pointer
One-number call
An example of a common function call:
// Self-contained header files
Void myfun (int x); // The statement can also be written as void myfun (INT );
Int main (INT argc, char * argv [])
{
Myfun (10); // call myfun (10) here; Function
Return 0;
}
Void myfun (int x) // A myfun function is defined here.
{
Printf ("% DN", X );
}
This myfun function is a function with no return value. It does not do anything. You should be familiar with this function calling format! View the writing format of the myfun function called in the main function:
Myfun (10 );
At the beginning, we only understood the function myfun in terms of functionality or mathematics. We knew that the myfun function name represents a function (or a piece of code ).
Until --
When I learned the function definition. I had to think: what is the function name?
(Don't think this is meaningless. Oh! You can see it later .)
Declaration of binary function pointer Variables
Just as the memory address of a Data variable can be stored in the corresponding pointer variable, the first address of the function is also stored in a function pointer variable. In this way, I can call the function pointed to through this function pointer variable.
In the C series language, any variable must be affirmed before it can be used. So should the function pointer variable be affirmed first? How can we declare it? In the preceding example, I declare a function pointer variable funp that can point to the myfun function. The following describes how to declare the funp variable:
Void (* funp) (INT); // You can also write it as void (* funp) (int x );
You can see that the declaration format of the entire function pointer variable is the same as that of the function myfun, but we just changed myfun to (* funp, in this way, there is a pointer funp that can point to the myfun function. (Of course, this funp pointer variable can also point to all other functions with the same parameters and return values .)
3. Call a function using the function pointer variable
With the funp pointer variable, we can assign values to myfun and call the myfun function through funp. Let's see how I use the funp pointer variable to call the myfun function:
// Self-contained header files
Void myfun (int x); // This statement can also be written as void myfun (INT );
Void (* funp) (INT); // It can also be declared as void (* funp) (int x), but this is generally not the case.
Int main (INT argc, char * argv [])
{
Myfun (10); // This is the direct call to the myfun Function
Funp = & myfun; // assign the address of the myfun function to the funp variable.
(* Funp) (20); // This is called by the function pointer variable funp.
}
Void myfun (int x) // A myfun function is defined here.
{
Printf ("% DN", X );
}
Please refer to the code and comments of the parts in the black Chinese text.
Run it. Well, it's good. The program runs well.
Oh, my feeling is: the relationship between myfun and funp is similar to that between int and int. The function myfun seems to be an int variable (or constant), while funp is a pointer variable like int.
Int I, * PI;
Pi = & I; // compare with funp = & myfun.
(How do you feel ?)
Well, it's not actually --
4. Other writing formats for calling Functions
Function pointers can also be used as follows to accomplish the same thing:
// Self-contained header files
Void myfun (int x );
Void (* funp) (INT); // declare a pointer variable used to point to the same parameter, return value function.
Int main (INT argc, char * argv [])
{
Myfun (10); // call myfun (10) here; Function
Funp = myfun; // assign the address of the myfun function to the funp variable.
Funp (20); // This is used to call the myfun function through the function pointer variable.
Return 0;
}
Void myfun (int x) // A myfun function is defined here.
{
Printf ("% DN", X );
}
I changed the black part (Please compare it with the previous Code ).
Run it! Same success.
Why?
Funp = myfun;
In this way, we can assign the same value of myfun to funp. Is myfun and funp the same data type (like the relationship between int and INT), rather than the relationship between int and int? (Are you confused ?)
It seems a little different from the previous code, right! That's why I said it!
Please let me not explain it to you for the time being. continue to look at the following situations (these can be code that can be correctly run !) :
Code 3:
Int main (INT argc, char * argv [])
{
Myfun (10); // call myfun (10) here; Function
Funp = & myfun; // assign the address of the myfun function to the funp variable.
Funp (20); // This is the function that calls the myfun function by referring to the needle variable.
Return 0;
}
Code 4:
Int main (INT argc, char * argv [])
{
Myfun (10); // call myfun (10) here; Function
Funp = myfun; // assign the address of the myfun function to the funp variable.
(* Funp) (20); // This is used to call the myfun function through the function pointer variable.
Return 0;
}
This is really the case!
(Wow! I really want to faint !)
What else! View --
Int main (INT argc, char * argv [])
{
(* Myfun) (10); // you can call the function name myfun in this format.
Return 0;
}
You may see it for the first time: function name calling can also be written like this! (It's just that we do not normally write like this .)
So what are the explanations?
Haha! Based on previous knowledge and experience, I think "New Discoveries" in this article will certainly come to the following conclusions:
1. In fact, the function name of myfun is the same as that of funp, that is, all function pointers. The myfun function name is a function pointer constant, and funp is a function number pointer variable, which is their relationship.
2. However, if you call a function name (* myfun) (10), it is inconvenient to write and read it. Therefore, the designers of C language can design and allow myfun (10); this form of calling (this is much more convenient and the function form in mathematics is the same, isn't it ?).
3. for uniformity, funp function pointer variables can also be called in the form of funp (10.
4. When assigning values, you can use funp = & myfun, or funp = myfun.
Whatever you like about the above Code!
Please understand this! This helps you to apply function pointers!
Last --
Note: In the Declaration of the function:
Void myfun (INT); // cannot be written as void (* myfun) (INT ).
Void (* funp) (INT); // It cannot be written as void funp (INT ).
(Please refer to the notes.
5. Define the pointer type of a function:
Just like a custom data type, we can define a function pointer type first, and then use this type to declare the function pointer variable.
Let me give you an example of a custom data type.
Typedef int * pint; // defines a pint alias for the int * type.
Int main ()
{
Int X;
Pint PX = & X; // It is equivalent to int * PX = & X. Pint type, which is actually int * type
* PX = 10; // PX is an int * type variable.
Return 0;
}
According to the notes, it is not difficult to understand it! (Although you may rarely use this definition, it will often be seen in later learning Win32 programming. )
Next, let's take a look at the definition and usage of the function pointer type: (Please compare with the above !)
// Self-contained header files
Void myfun (int x); // The statement can also be written as void myfun (INT );
Typedef void (* funtype) (INT); // This is just to define a function pointer type
Funtype funp; // use the funtype type to declare the global funp variable.
Int main (INT argc, char * argv [])
{
// Funtype funp; // The function pointer variable can also be local, so please declare it here.
Myfun (10 );
Funp = & myfun;
(* Funp) (20 );
Return 0;
}
Void myfun (int x)
{
Printf ("% DN", X );
}
Look at the simhei part:
First, add a typedef before void (* funtype) (INT); to define a function pointer type named funtype, rather than a funtype variable.
Then, the funtype funp; statement declares a funp variable like pint PX.
Others are the same. The entire program has done the same thing.
The advantages of this method are:
With the funtype type, we can easily declare multiple function pointer variables of the same type with the funtype type. As follows:
Funtype funp2;
Funtype funp3;
//......
Six function pointers are used as parameters of a function.
Since the function pointer variable is a variable, it can also be used as a function parameter. Therefore, you should also know how function pointers are transmitted and used as parameters of a function.
Here is an example:
Requirement: I want to design a callmyfun function. This function can call the myfun1, myfun2, and myfun3 functions by using different function pointer values in the parameter. (Note: the format of the three functions must be the same ).
Implementation: The Code is as follows:
// Self-contained header files
Void myfun1 (int x );
Void myfun2 (int x );
Void myfun3 (int x );
Typedef void (* funtype) (INT); // ②. Define a function pointer type funtype.
Void callmyfun (funtype FP, int X );
Int main (INT argc, char * argv [])
{
Callmyfun (myfun1, 10); // ⑤. Use the callmyfun function to call three different functions.
Callmyfun (myfun2, 20 );
Callmyfun (myfun3, 30 );
}
Void callmyfun (funtype FP, int X) // ③. the type of the parameter FP is funtype.
{
FP (x); // ④. Execute the passed function through the FP pointer. Note that the function referred to by FP has a parameter
}
Void myfun1 (int x) // ①. This is a function with a parameter. The following two functions are the same.
{
Printf ("output in the function myfun1: % DN", X );
}
Void myfun2 (int x)
{
Printf ("output in function myfun2: % DN", X );
}
Void myfun3 (int x)
{
Printf ("output in function myfun3: % DN", X );
}
Output result: omitted
Analysis: (see my comments. You can analyze it by yourself in the order of my comments ① ③ ④ .)