Deep study of function pointers and left-right rules in C language _c language

Source: Internet
Author: User
Tags constant

The usual function calls
An example of a common function call:

Contains the header file
void myfun (int x) itself;//This statement can also be written as: void myfun (int);

int main (int argc, char* argv[])
{
  myfun (10);//Here is call Myfun (10); function return

   0;
}

void myfun (int x)//is defined here as a myfun function
{
  printf ("%d\n", x);
}

The Myfun function is a function that has no return value, and it does not do anything. The format of this call function you should be very familiar with it! Look at the writing format for calling the Myfun function in the main function:
Myfun (10);
We started with the function, or mathematically, to understand myfun, knowing that myfun function names represent a feature (or a piece of code).
Until--
When you learn about the concept of function pointers. I have to think: what is the name of the letter?
(Don't think it's meaningless.) Oh, continue to look down you will know. )

Declaration of function Pointer variable
Just as the memory address of a data variable can be stored in the corresponding pointer variable, the first address of the function is stored in a function pointer variable. In this way, I can use the function pointer variable to invoke the function being pointed to.
In the C-series language, any variable is always declared before it can be used. So the function pointer variable should also be stated first? And how is that to be affirmed? Take the example above, I declare a function pointer variable FUNP that can point to the Myfun function. Here's how to declare the FUNP variable:
void (*FUNP) (int); Can also be written as void (*FUNP) (int x);
You see, the entire function pointer variable's declaration format is the same as the function Myfun declaration, except that--we change the myfun to (*FUNP), so we have a pointer to the Myfun function FUNP. (Of course, this FUNP pointer variable can also point to all other functions that have the same parameters and return values.) )

Calling functions by Function pointer variables
with the FUNP pointer variable, we can assign a value to the myfun and then invoke the Myfun function by FUNP. See how I can invoke the Myfun function by FUNP the pointer variable:

Contains the header file
void myfun (int x) itself;//This declaration can also be written as: void myfun (int);
void (*FUNP) (int); It can also be declared void (*FUNP) (int x), but it is not customary in general.

int main (int argc, char* argv[])
{
  myfun (10);//This is directly calling the Myfun function
  funp=&myfun;//Assigning the address of the Myfun function to the FUNP variable
  (*FUNP) (20); This is through the function pointer variable FUNP to invoke the Myfun function.
}

void myfun (int x)//is defined here as a myfun function
{
  printf ("%d\n", x);
}

See the code and comments in the boldface section.
Run to see. Well, yes, the program works very well.
Oh, my feeling is: the type relationship between Myfun and FUNP is similar to the relationship between int and int *. The function myfun seems to be a variable (or constant) such as int, while FUNP is like a pointer variable such as int *.

int i,*pi;
pi=&i;  Compared with Funp=&myfun.

(How do you feel?) )
Oh, it's not--

Other writing formats for calling functions
function pointers can also be used to accomplish the same thing:

Contains the header file
void myfun (int x) itself; 
void (*FUNP) (int); Declares a pointer variable that is used to point to the same parameter and return a value function.

int main (int argc, char* argv[])
{
  myfun (10);//This is called myfun (10); function
  Funp=myfun;//Assign the address of the Myfun function to the FUNP variable
  FUNP (20);//This is the function pointer variable to invoke the Myfun function. return

   0;
}

void myfun (int x)//is defined here as a myfun function
{
  printf ("%d\n", x);
}

I changed the bold character section (please compare yourself with the previous code).
Run and try, Ah! Succeed as well.
Hey?

Funp=myfun;

It is possible to assign myfun values to FUNP, so is myfun and FUNP the same data type (that is, the relationship between int and int), rather than the relationship between int and int*? (Is there a little bit of confusion?) )
It seems to be a little contradictory with the previous code, right! So I say!
Please allow me to temporarily not explain to you, continue to look at the following situations (these can be the right to run the code yo!) ):
Code Three:

int main (int argc, char* argv[])
{
  myfun (10);//Here is the call Myfun (10); function
  funp=&myfun;// Assigns the address of the Myfun function to the FUNP variable
  FUNP (20);//This is the function pointer variable to invoke the Myfun function. return

   0;
}

Code four:

int main (int argc, char* argv[])
{
  myfun (10);//Here is call Myfun (10); function
  Funp=myfun;//Assign the address of the Myfun function to the FUNP variable
  (*FUNP) (20); This is done by using the function pointer variable to invoke the Myfun function. return

   0;
}

It really can be this way oh!
Wow It's going to faint! )
And there! Look--

int main (int argc, char* argv[])
{
  (*myfun) (10)//See, Function name Myfun can also have such a call format return

   0;
}

You may have seen it for the first time: function name invocation can also be written like this! (It's just that we don't usually write like this.) )
So, what does all this mean?
Oh! If I were "Sherlock Holmes", based on previous knowledge and experience to infer the "new findings", it will be analyzed and inferred the following conclusions:
1. In fact, myfun function names and FUNP function pointers are the same, that is, are function pointers. The Myfun function name is a function pointer constant, and FUNP is a function number pointer variable, which is their relationship.
2. But if the function name is called (*myfun) (10), then it is inconvenient and unaccustomed to write and read. So the designers of C language will design and allow Myfun (10), this form of invocation (so much more convenient and as in the mathematical form of functions, is not it?) )。
3. For the sake of unification, the FUNP function pointer variable can also be invoked in the form of FUNP (10).
4. When assigning value, can funp=&myfun form, also can funp=myfun.
The above code writing, whatever you love how!
Please understand this! This is useful for your application to function pointers!
Finally--
Add a point: in the declaration of a function:

void myfun (int);  cannot be written as void (*myfun) (int).
void (*FUNP) (int);  cannot be written as a void funp (int).

(see note) This is to be noted.

Defines a pointer type for a function:
Just like a custom data type, we can also define a function pointer type and then use that 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
int main ()
{
 int x for
 the int* type; Pint px=&x; is equivalent to the int * px=&x;. The pint type is actually the int * type
 *px=10;//px is the int* type of variable return 
 0;
}

According to the note, should not ugly understand it! (although you may rarely use this definition, you will often see it later when you learn Win32 programming.) )
Let's take a look at the definition and use of the function pointer type: (please check against it!) )

Contains the header file
void myfun (int x) itself;//This statement can also be written as: void myfun (int);
typedef void (*funtype) (int); This simply defines a function pointer type
funtype FUNP//And then declares the global FUNP variable

int main (int argc, char* argv[]) with the Funtype type.
Funtype FUNP; The function pointer variable, of course, can also be local, so please declare it here. 
  Myfun (ten); 
  funp=&myfun; 
  (*FUNP) (a); 

   return 0;
}

void myfun (int x) 
{
  printf ("%d\n", x);
}

Look at the Bold section:
First, in Void (*funtype) (int); A typedef was added to the front. This simply defines a pointer type named Funtype function, not a funtype variable.
Then, Funtype FUNP; This sentence is like Pint px; declare a FUNP variable.
The other is the same. The whole program completes the same thing.
The advantages of such an approach are:
With the Funtype type, we can use the Funtype type to declare multiple function pointer variables of the same type, just as easily. As follows:

Funtype FunP2;
Funtype FunP3;
......

function pointer as an argument to a function
Since the function pointer variable is a variable, it can, of course, be used as a parameter to a function. So, you should also know how a function pointer is passed as a parameter to a function.
Give you an example:
Requirements: I want to design a callmyfun function, which can be called MyFun1, MyFun2, MyFun3 by different function pointer values in the parameters (note: These three functions should be defined in the same format).
Implementation: The code is as follows:

Contains the header file 
void MyFun1 (int x) itself; 
void MyFun2 (int x); 
void MyFun3 (int x); 
typedef void (*funtype) (int); ②. Defines a function pointer type funtype, with ① function type one to
void Callmyfun (Funtype fp,int x);

int main (int argc, char* argv[])
{
  callmyfun (myfun1,10)//⑤. Call three different functions by Callmyfun function
  Callmyfun (MyFun2, ); 
  Callmyfun (myfun3,30); 
}
void Callmyfun (Funtype fp,int x)//③. The type of parameter FP is funtype.
{
 fp (x);//④ the function passed in through the FP pointer, note that FP refers to a function that has a parameter of
}
void MyFun1 (int x)//①. This is a function with one parameter, and the following two functions are the same
{
  printf (output in function MyFun1:%d\n, x);
}
void MyFun2 (int x) 
{
  printf (output in function MyFun2:%d\n, x);
}
void MyFun3 (int x) 
{
  printf (output in function MyFun3:%d\n, x);
}

Output result: slightly

Analysis: (see the Notes I wrote.) You can analyze the ①②③④⑤ order of my comments. )

The above part is the reprint Netizen said. The original address is: http://blog.pfan.cn/whyhappy/6030.html


Address jump
void (*reset) (void) = (void (*) (void)) 0.
void (*reset) (void) is the function pointer definition, (void (*) (void) 0 is a force type conversion operation, and the value "0" is cast to the function pointer address "0".
By calling the Reset () function, the program jumps to the "0" address where the program executes and executes again. In some of the other advanced SCM bootloader, such as Nboot, Uboot, EBoot, often through these bootloader to download the program, and then through the function pointer to the address of the program to be executed.
1 void (*theuboot) (void);
。。。。
Theuboot = (void (*) (void)) (0x30700000);
Theuboot ();
。。。。。
2 (* (void (*) (void)) (0x30700000)) ();
Force type conversions, convert an absolute address to a function pointer, and call this function to jump to the absolute address mentioned earlier.
Translation into the assembly is:
MOV r0,0x30700000;
MOV pc,r0
for (* (void (*) (void)) (0x30700000)) ();
You can understand that.
First (void (*) (void) is a mandatory type conversion, and he forces the unsigned integer at the back of the 0x30700000 into a function pointer, which points to a function entry argument void and the return value is void.   If you understand this step, then the expression (void (*) (void)) (0x30700000) is FP, and the expressions above can be simplified to (*FP) (); OK, so it's clear that we're going to refer to the function pointer that was transformed above (that is, the function that the function pointer points to).


Right left rule

C language has complex pointer declarations, all of which are made up of various declaration nesting. Large companies in the pen test often appear to understand the complex pointer statement, the right left rule is a well-known and commonly used method.
The Right-left Rule:start reading the declaration from the innermost parentheses, go rigtht, and then down. When you encounter parentheses, the direction should to be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been.

Right-left rule: First look at the innermost brackets, then look to the right and look left. Whenever you encounter parentheses, you should turn the reading direction. Once you have parsed everything inside the parentheses, jump out of the parentheses. Repeat this process until the entire declaration is resolved.

The original author fixes this: it should be an identifier that has never been defined, rather than read from parentheses, an undefined identifier because there may be multiple identifiers in a declaration, but undefined identifiers will have only one

Example

  


First you find the undefined identifier, which is Func, which has a pair of parentheses outside, and a * on the left, indicating that Func is a pointer. And then jump out of parentheses, look to the right, is also a bracket, which means (*func) is a function, and func is a pointer to such a function, that is, a function pointer. Such functions have arguments of type int*, and the return value type is int

  Int (*func) (int *p, int (*f) (int *)); 


Func is included in a pair of parentheses, and the left has a * number, indicating that func is a pointer, and then jump out of this parenthesis, first look to the right, but also a parenthesis, that Func is a function pointer. Such functions have parameters such as int * and INT (*) (int *), and the return value is int. For the formal parameters of int (*f) (int *), the parsing method is consistent with Func

  Int (*func[5]) (int *p); 


Func to the right is an [] operator, description func is an array of 5 elements with a * on the left side of the Func, indicating that the Func element is a pointer, note that the * is not decorated func, but is decorated with func[5] because the [] operator has a higher precedence than *. Func with [], so the func[5 is modified. Jump out of this bracket and look to the right, which is also a pair of parentheses, which shows that the element of the Func array is a pointer to a function type, which points to a function that has a parameter of type int*, and the return value type is int

  Int (* (*FUNC) [5]) (int *p); 


Func is surrounded by a pair of parentheses, left another *, then Func is a pointer, jump out of parentheses, the right is a [] operation symbol, indicating that func is a pointer to the array, now look to the left, there is a * number on the left, indicating that the elements of this array is a pointer, then jump out of parentheses, to the right There is also a bracket to the right, indicating that the element of this array is a pointer to the function. To sum up: Func is a pointer to an array whose elements are function pointers that have int * parameters and return functions of type int

  Int (* (*func) (int *p)) [5]; 


Func is a function pointer that has a parameter of type int, and the return value is a pointer to an array that points to an array of 5 elements of type int.

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.