Explanation of function pointers and pointer functions

pointer function

Pointer function:
Also called pointer function, it is essentially a function, a special function type that returns a pointer as the return value of the function.
Format of pointer function declaration:
Return type * function name (parameter list);
or < a i=5> Return type * function name (parameter list);. Among them, the return type is a pointer type, the function name is the name of the pointer function, and the parameter list is the parameter list of the pointer function.

推荐使用第一种声明方式。更清晰明了

For example:
Ordinary function (that is, the return value is not an address)

int fun0(int);//声明了一个返回值类型为int,函数参数为int型的函数。

Pointer function (that is, the return value is the address)

int* fun1 (int);//声明了一个返回值为整型的指针,函数参数为int,int的指针型函数。
void* fun2 (int, int);//声明了一个返回值为void型的指针,函数参数为int,int的指针型函数。

注意:Pointer functions must have a return value, and the return value type is in the form of void*, which is any pointer type. Instead of returning no value. Regardless of whether the returned value is int* or void*, it is recommended to determine whether it is a null pointer.

example:

int* func(int a, int b);//指针型函数声明; 或者为 int* func(int, int);即声明里的形参可以只写类型,不写形参变量。这也是推荐的写法。
	
int* func(int a, int b) //指针型函数的定义
{
   int* p = (int*)malloc(sizeof(int));//在堆内存中申请了一块4个字节的内存,并把指向这块堆内存的地址返回,赋值给指针变量p
   *p = a + b;//将a+b的和,赋值给指针变量p所指向的内存空间。注:当*p作为左值时,表示的就是它所指向的那块内存对应的变量。
   return p;
}

注意:Like ordinary functions, when a pointer function has no formal parameters, the parentheses () following the declaration cannot be omitted, otherwise it will become the definition of a pointer variable.

The pointer function is an ordinary function, so ordinary just because of its函数返回值是地址值. The only difference between this and other general functions
is that there is an extra * sign in front of the function name, and this function is a pointer function.
One sentence summary: What is returned is the address value. When the pointer function is called, a pointer variable is used to receive the address value returned by the pointer function.

function pointer

The function pointer is a pointer variable pointing to a function, that is, it is essentially a pointer variable. Therefore the "function pointer" itself should first be a pointer variable.
But the pointer variable points to the function. This is just like using pointer variables to point to integer variables, character types, and arrays. Here, they point to functions. When C/C++ is compiled, each function has an entry address, which is the address pointed by the function pointer. After you have a pointer variable pointing to a function, you can use the pointer variable to call the function, just like you can use a pointer variable to refer to other types of variables. These concepts are generally consistent. Function pointers have two uses: calling functions and serving as function parameters.

First look at the declaration of an int type pointer, and then compare it with a function pointer:

int* p;

Declare a pointer of type function (for example, a pointer with two parameters of type int and a return value of type int):

int (*fun_ptr) (int, int);//定义 一个【有两个int类型的参数以及一个int类型的返回值】类型 的函数指针。fun_ptr 就是指针变量名

So this pointer can be used to point to: any function that conforms to 一个有两个int类型的参数以及一个 int类型的返回值.
Insert image description hereThe only difference between the two is that the function pointer has an additional parameter list
Example:

#include <iostream>
#include <stdio.h>

void Fun(int a, int b){//函数定义
    std::cout << "a =" << a <<", b=" << b <<std::endl;
};

int Fun1(int a, int b){//函数定义
    std::cout << "a =" << a <<", b=" << b <<std::endl;// a = 2, b = 3
    return 0;
};

int main(int argc, char *argv[])
{

   void (*fun_ptr) (int, int);//定义一个函数指针 

    fun_ptr = Fun;//函数名其实就是函数的地址,函数可以看成和数组名一样都是一个指针常量,即指针的指向地址不可改变
   // fun_ptr = Fun1;//编译报错,函数指针(fun_ptr)的类型 和 Fun1函数的类型不一致。必须要保证返回值和参数列表一样。否则函数指针不能指向此函数地址

    // std::cout << "Fun函数地址:" << Fun <<std::endl;//这样方式打印函数地址会把函数指针转换为bool类型,故打印出来的是总是1,改用下面的printf函数
    fun_ptr(2,3);//使用函数指针来调用函数
    printf("Fun函数的地址为:%p\n",Fun);//Fun函数的地址为:0x400910
    printf("Fun1函数的地址为:%p\n",Fun1);//Fun1函数的地址为:0x400922
    printf("fun_ptr的指向地址:%p\n",fun_ptr);//fun_ptr的指向地址:0x400910
}

The difference between the definition of a function pointer and the declaration of a pointer function

Definition of function pointer

void (*fun) (int, int);//fun 是一个有两个int类型的参数以及一个 int类型的返回值的函数指针。//指针就是变量。变量名是fun.

注意:The difference between pointers and addresses is mentioned here. A pointer is a variable, which is used to store an address, while an address is a constant value. Similar to the relationship between variables and their values.

pointer function declaration

void* fun (int, int);//fun是返回一个指针的函数

注意:When defining a function pointer, the first () cannot be omitted. If omitted, it will lead to a completely different situation. It becomes a declaration of a pointer function.

The use of typedef in function pointers

The typedef operator is frequently used in C/C++. It's not just possible to alias simple types. You can also give complex types aliases.
The format is as follows:
typedef type alias;
Another function of using is introduced in C++11 to provide Type alias. The function of using is the same as that of typedef. They are equivalent. Using using on some complex types is easier to understand intuitively than using typedef.
The format is as follows:
using alias = type;
注意: The previous function of using is to introduce namespaces such as the standard library. Namespace: using namespace std;

typedef and using alias the type of function pointer

The application of typedef in aliasing function pointer types (this is also the application of typedef in aliasing complex types):

typedef void (*FUN) (int, int);//这里的FUN是一种 void (*) (int, int) 类型的别名,而不是上面的函数指针,而是一个类型。可以FUN来表示 函数指针 的类型。

注意: Maybe writing typedef void (*) (int, int) FUN; is more consistent with the format of "typedef type alias;". But writing this way will cause a compilation error, which means this way of writing is wrong.
You can also use using to get aliases (supported in C++11)

	using FUN = void (*) (int, int);//感觉这样方式更符合理解。这也是为啥C++11中开始支持使用using来给类型取别名的意义。

注意:Regardless of typedef or using, they give an alias to an existing simple type or complex type, rather than creating a new type.

example:

#include <iostream>
#include <stdio.h>

typedef void (*FUNC) (int, int);//使用typedef来取别名
using FUNC1 = void (*) (int, int);//使用using来取别名
using FUNC2 = int (*) (int, int);//使用using来取别名

void Fun(int a, int b){//函数定义
    std::cout << "a =" << a <<", b=" << b <<std::endl;
};

int Fun1(int a, int b){//函数定义
    std::cout << "a =" << a <<", b=" << b <<std::endl;
    return 0;
};

int main(int argc, char *argv[])
{

    FUNC fun_ptr = Fun; //比直接 void (*fun_ptr) (int, int) = Fun;写简洁
    FUNC1 fun_ptr1 = Fun; //比直接 void (*fun_ptr1) (int, int) = Fun;写简洁
    FUNC2 fun_ptr2 = Fun1; //比直接 int (*fun_ptr2) (int, int) = Fun1;写简洁

     // std::cout << "Fun函数地址:" << Fun <<std::endl;//这样方式打印函数地址会把函数指针转换为bool类型,故打印出来的是总是1,改用下面的printf函数
    fun_ptr(2,3);//使用函数指针来调用函数  // a = 2, b = 3
    fun_ptr1(5,3);//使用函数指针来调用函数 // a = 5, b = 3
    fun_ptr2(6,3);//使用函数指针来调用函数 // a = 6, b = 3
    printf("Fun函数的地址为:%p\n",Fun);//Fun函数的地址为:0x400910
    printf("Fun1函数的地址为:%p\n",Fun1);//Fun1函数的地址为:0x400922
    printf("fun_ptr的指向地址:%p\n",fun_ptr);//fun_ptr的指向地址:0x400910
    printf("fun_ptr1的指向地址:%p\n",fun_ptr1);//fun_ptr1的指向地址:0x400910
    printf("fun_ptr2的指向地址:%p\n",fun_ptr2);//fun_ptr2的指向地址:0x400922
    return 0;
}

typedef and using alias the type of the function

You can also give aliases to function types

typedef void FUNC4(int, int);//使用typedef来给函数的类型取别名,不看 前面的typedef 单独看 void FUNC4(int, int);是一个函数声明,即函数原型。

Compare with function pointer alias:

typedef void (*FUNC) (int, int);//使用typedef来给函数指针的类型取别名
分析:
//void (*FUNC) (int, int); //定义一个 返回值为void,拥有两个int参数类型的 函数指针,函数指针名称为FUNC
//void FUNC4(int, int); //声明一个 返回值为void,拥有两个int参数类型的 函数,此函数的函数名是 FUNC4.
//它们就是一个表示 函数指针,一个表示函数
//同理 形如上面的 两者前面都加上typedef后,FUNC表示的函数指针的类型别名。 FUNC4表示的函数的类型的别名。

Complete code demo:

#include <iostream>
#include <stdio.h>

typedef void (*FUNC) (int, int);//使用typedef来给函数指针的类型取别名
typedef void FUNC4(int, int);//使用typedef来给函数的类型取别名,不看 前面的typedef 单独看 void FUNC4(int, int);是一个函数声明,即函数原型。
//或者使用using
//using FUNC = void (*) (int,int); //等号右侧表示函数指针的类型
//using FUNC4 = void (int,int); //等号右侧表示函数的类型
//两个类型的区别就是一个有*,一个没有*


//void (*FUNC) (int, int); //定义一个 返回值为void,拥有两个int参数类型的 函数指针,函数指针名称为FUNC
//void FUNC4(int, int); //声明一个 返回值为void,拥有两个int参数类型的 函数,此函数的函数名是 FUNC4.
//它们就是一个表示 函数指针,一个表示函数
//同理 两者前面都加上typedef后,FUNC表示的函数指针的类型别名。 FUNC4表示的函数类型的别名。

void Fun(int a, int b){//函数定义
    std::cout << "a =" << a <<", b=" << b <<std::endl;
};

int Fun1(int a, int b){//函数定义
    std::cout << "a =" << a <<", b=" << b <<std::endl;
    return 0;
};

int main(int argc, char *argv[])
{
    FUNC fun_ptr = Fun; //比直接 void (*fun_ptr) (int, int) = Fun;简洁
    FUNC4* fun_ptr3 = Fun;// 在FUNC4后加* 表示的就是函数指针的类型。可以这样理解 FUNC4是函数的类型 FUNC4*就是指向 和FUNC4相同类型的函数地址 的指针的类型。
    //(void (int,int))* fun_ptr3 = Fun; //直接这样写语义会报错,这也就是为啥用typedef来给复杂类型取别名的用处,至于编译解析交给编译器完成。

    // std::cout << "Fun函数地址:" << Fun <<std::endl;//这样方式打印函数地址会把函数指针转换为bool类型,故打印出来的是总是1,改用下面的printf函数
    fun_ptr(2,3);//使用函数指针来调用函数  // a = 2, b = 3
    fun_ptr3(5,3);//使用函数指针来调用函数 // a =5, b=3
    printf("Fun函数的地址为:%p\n",Fun);//Fun函数的地址为:0x400910
    printf("fun_ptr3的指向地址:%p\n",fun_ptr3);//fun_ptr的指向地址:0x400910
    return 0;
}

Guess you like

Origin blog.csdn.net/adminstate/article/details/134749185