A basic learning guide to function pointers in C language _c language

Source: Internet
Author: User
Tags function prototype

As the name suggests, a function pointer is a pointer to a function. It is a pointer to a function. See Example:

A

char * (*FUN1) (char * P1,char * p2);

B

char * *FUN2 (char * p1,char * p2);

C

char * FUN3 (char * p1,char * p2);

What do you mean by looking at the three expressions above?

C) This is easy, Fun3 is the function name, P1,P2 is the parameter, its type is char * type, the function's return value is char * type.
B) is also very simple, compared with the C-expression, the only difference is that the return value type of the function is char** and is a two-level pointer.
A) fun1 is the function name? Recall the case when you explained the array pointer earlier. We say that the array pointer is so defined and perhaps clearer:

Int (*) [ten] p;

And then look at a. How similar the expression is here! Get it. Here fun1 is not a function name, but a pointer variable, which points to a function. This function has two parameters for the pointer type, and the return value of the function is also a pointer. Again, let's rewrite this expression:

char * (*) (char * P1,char * p2) fun1;

Isn't it better to look good? Unfortunately, the compiler doesn't think so. ^_^.


function pointers and a simple function

Let's start with a very simple "Hello world" function to see how to create a function pointer.

#include <stdio.h>
 
//function prototype
void SayHello ();
 
function implementation
void SayHello () {
  printf ("Hello world\n");
}
 
The main function calls
int main () {
  sayhello ();
}

We define a function called SayHello, which does not return a value or accept any arguments. When we call it in the main function, it prints out "Hello World" to the screen. Very simple. Next, we rewrite the main function, the SayHello function that was called directly before, and now call it using the function pointer instead.

int main () {
  void (*sayhelloptr) = SayHello;
  (*SAYHELLOPTR) ();
}

The syntax for the second line of Void (*SAYHELLOPTR) () looks a bit strange, and we'll analyze it step-by-step.

Here, the function of the keyword Void is that we create a function pointer and let it point to a function that returns void (that is, no return value).
Just as any other pointer must have a name, here Sayhelloptr is treated as the name of the function pointer.
We use the * notation to indicate that this is a pointer, which is no different from declaring a pointer to an integer or character.
*sayhelloptr the brackets at both ends are required, otherwise, the declaration becomes void *sayhelloptr (), and * takes precedence over void, and becomes a declaration of a normal function that returns a pointer to void. Therefore, it is critical that you do not forget to add parentheses when declaring a function pointer. The
argument list is immediately after the pointer name, which, in this case, is a pair of empty parentheses () because there are no arguments.
Combining the above points, the meaning of void (*syahelloptr) is very clear, a function pointer that points to a function that does not receive parameters and does not return a value.
in the second line of code above, void (*sayhelloptr) = SayHello, we assign the function name SayHello to our newly created function pointer. More details about the function name, which we'll discuss later, can now be viewed as a label that represents the address of a function and can be assigned to a function pointer. This is the same as the statement int *x = &myint; We assign the address of the Myint to a pointer to an integer. Just when we think about the function, we don't need to add an address character &. In short, the function name is its address. Then look at the third line, we use the Code ' (*SAYHELLOPTR) (); · ' Dereference and called the function pointer.

After the second row is declared, sayhelloptr as the name of the function pointer, no different from any other pointers, and can store values and assign values.
We refer to the Sayhelloptr solution in the same way as any other pointer, that is, to use the dereference character * before the pointer, which is the *sayhelloptr in the code.
Again, we need to add parentheses at both ends, i.e. (*sayhelloptr), otherwise it will not be treated as a function pointer. So remember to declare a reconciliation quote with parentheses at both ends.
The bracket operator is used for function calls in the C language, and if there are parameters involved, put them in parentheses. This is also similar to the function pointer, which is (*SAYHELLOPTR) () in the code.
This function has no return value and there is no need to assign it to any variable. Alone, this call is no different from SayHello.
Next, we'll modify the function slightly. You will see the strange syntax of the function pointer, as well as the phenomenon of invoking the function pointer after the assignment using the method called the normal function.

int main () {
void (*sayhelloptr) = SayHello;
Sayhelloptr ();
}

As before, we assign the SayHello function to the function pointer. But this time, we call it using the method of calling a normal function. I'll explain this when I talk about the function name later, but now I just need to know that (*SYAHELLOPTR) () and Syahelloptr () are the same.

function pointers with parameters

Well, this time we're going to create a new function pointer. The function it points to still does not return any values, but with arguments.

#include <stdio.h>
 
//function prototype
void subtractandprint (int x, int y);
 
function implementation
void Subtractandprint (int x, int y) {
  int z = x-y;
  printf ("Simon says, the answer is:%d\n", z);
}
 
The main function calls
int main () {
  void (*sapptr) (int, int) = Subtractandprint;
  (*SAPPTR) (2);
  Sapptr (2);
}

As before, the code includes function prototypes, function implementations, and statements executed by function pointers in the main function. The feature in the prototype and implementation is changed, and the previous SayHello function does not accept any arguments, and this time the function Subtractandprint accept two int as parameters. It subtracts two parameters one at a time and then prints to the screen.

In line 14th, we created the SAPPTR function pointer through ' (*SAPPTR) (int, int) ', and the previous distinction was simply to replace the original empty bracket with (int, int). This is consistent with the feature of the new function.
In line 15th, the dereference and execute functions are exactly the same as before, with the addition of two parameters in parentheses, which is changed to (10, 2).
On line 16th, we call the function pointer using the method that calls the normal function.


function pointer with parameter with return value

This time, we'll change the Subtractandprint function to a function called subtract, so that it returns the result that was originally printed to the screen.

#include <stdio.h>
 
//function prototype
int subtract (int x, int y);
 
function to implement
int subtract (int x, int y) {return
  xy;
}
 
The main function calls
int main () {
 int (*subtractptr) (int, int) = subtract;
 
 int y = (*subtractptr) (2);
 printf ("Subtract gives:%d\n", y);
 
 int z = subtractptr (2);
 printf ("Subtract gives:%d\n", z);
}

This is very similar to the Subtractandprint function, except that the subtract function returns an integer, and the feature label is certainly different.

In line 13th, we created the subtractptr this function pointer through int (*SUBTRACTPTR) (int, int). The difference with the previous example is that the void is replaced with an int to represent the return value. This is consistent with the subtract function's characteristic standard.
In line 15th, the dereference and execution of this function pointer, in addition to assigning the return value to Y, is no different from calling Subtractandprint.
On line 16th, we output the return value to the screen.
18 to 19 lines, we call the function pointer using the method called the normal function, and output the result.
It's the same as before, we just added the return value. Let's look at another slightly more complex example--passing the function pointer to another function as an argument.

Pass the function pointer as a parameter

We have seen the various situations where function pointers are declared and executed, regardless of whether they take parameters or whether there are return values. Next we use a function pointer to perform different functions based on different inputs.

#include <stdio.h>
 
//function prototype
int add (int x, int y);
int subtract (int x, int y);
int Domath (int (*mathop) (int, int), int x, int y);
 
Addition x+ y
int Add (int x, init y) {return
  x + y;
}
 
Subtraction x-y
int subtract (int x, int y) {return
  xy;
}
 
Executes the function pointer
int domath (int (*mathop) (int, int), int x, int y) {return
  (*mathop) (x, y) by input
.
 
The main function calls
int main () {
 
//domath
int a = Domath with addition (add, 2);
printf ("Add gives:%d\n", a);
 
Call Domath
int b = Domath (subtract, 2) with subtraction;
printf ("Subtract gives:%d\n", b);
}

Let's take one step at a a-one-step analysis.

We have two features with the same function, add and subtract, and they all return an integer and accept two integers as arguments.
In line sixth, we define the function int domath (int (*mathop) (int, int), int x, int y). Its first argument int (*mathop) (int, int) is a function pointer to a function that returns an integer and accepts two integers as arguments. That's the syntax we've seen before, no different. The latter two integer arguments are used as simple inputs. So, this is a function that takes a function pointer and two integers as arguments.
19 to 21 lines, the Domath function passes its own two integer arguments to the function pointer and calls it. Of course, it can also be called like this. Mathop (x, y);
There are 27 to 31 lines of code that we haven't seen before. We called the Domath function with the function name as an argument. As I said before, the function name is the address of the function and can be used in place of the function pointer.
The main function calls the two-time domath function, once with add, once with the subtract, and output the two results.

Name and address of the function

Now that we have a prior engagement, let's discuss the function name and address as the end of it. A function name (or label) is converted to a pointer itself. This means that the function name can be used where the function pointer is required as input. This also causes some seemingly bad code to run correctly. Look at the example below.

#include <stdio.h>
 
//function prototype
void Add (char *name, int x, int y);
 
addition x + y
void Add (char *name, int x, int y) {
  printf ("%s gives:%d\n", name, x + y);
}
 
The main function calls
int main () {
 
  
//Some bad function pointer assignment
  void (*add1ptr) (char*, int, int) = add;
  void (*add2ptr) (char*, int, int) = *add;
  void (*add3ptr) (char*, int, int) = &add;
  void (*add4ptr) (char*, int, int) = **add;
  void (*add5ptr) (char*, int, int) = ***add;
 
  
Still able to operate normally
  (*ADD1PTR) ("Add1ptr", 2);
  (*ADD2PTR) ("Add2ptr", 2);
  (*ADD3PTR) ("Add3ptr", 2);
  (*ADD4PTR) ("Add4ptr", 2);
  (*ADD5PTR) ("Add5ptr", 2);
 
  
Of course, this can also run
  add1ptr ("Add1ptrfunc", 2);
  Add2ptr ("Add2ptrfunc", 2);
  Add3ptr ("Add3ptrfunc", 2);
  Add4ptr ("Add4ptrfunc", 2);
  Add5ptr ("Add5ptrfunc", 2);
}

This is a simple example. Run this code and you'll see that every function pointer executes, and you just get some warnings about character conversions. However, these function pointers work correctly.

On line 15th, add, as the function name, returns the address of the function, which is implicitly converted to a function pointer. As I mentioned earlier, when a function pointer is required as input, the function name can be used.
On line 16th, the dereference character acts on the add before, that is, *add, which returns the function at this address. Then, like the function name, it is implicitly converted to a function pointer.
on line 17th, the address character is used before add, that is, &add, returns the address of the function, and then gets a function pointer.
18 through 19 lines, add continues to dereference itself, returns the function name, and is converted to a function pointer. In the end, their results are no different from the function names.
Obviously, this code is not a good instance code. We get the following knowledge: First, the function name will be implicitly converted to function pointers, as in the case of passing as a parameter, the array name is implicitly converted to the same pointer. Function names can be used anywhere a function pointer is required to be entered. Second, the solution reference character * and the address character & used before the function name are basically redundant.

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.