函数指针和指针函数

指针

指针函数

指针函数一个函数,只不过这个函数的返回值是一个地址值

  • 和普通函数唯一的区别就是在函数名前面多了一个*号

    函数返回值必须用同类型的指针变量来接受

    也可以将其返回值定义为 void*类型,在调用的时候强制转换返回值为自己想要的类型

struct Data{
    int a;
    char b;
    void show(){
        cout << a << "," << b << endl;
    }
};
//指针函数
Data* fun(int a,char b){
    Data *tmp = new Data;
    tmp->a = a;
    tmp->b = b;
    return tmp;
}
int main(){
    Data *aa = fun(100, 'c');
    aa->show();
    return 0;
}

采用强制类型转换

//指针函数,返回值改为void*
void* fun(int a,char b){
 Data *tmp = new Data;
 tmp->a = a;
 tmp->b = b;
 return tmp;
}
int main(){
 //强制类型转换
 Data *aa = static_cast<Data*>(fun(200,'v'));
 aa->show();
 return 0;
}

例子2:

int *f(int, int);
int main(){
int *p = nullptr;
p = f(100, 200);
cout << "The memory addr is" << p << endl;
cout << "The value is" << *p << endl;
return 0;
}
//函数定义
int* f(int a,int b){
int *p = new int;
cout << "The memory addr is" << p << endl;
*p = a * b;
cout << "The value is" << *p << endl;
return p;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

发现输出的地址是相同的

指针函数就是返回一个地址给调用者,用于需要地址的情况

函数指针

函数指针就是一个指针,但这个指针指向的函数,不是普通的基本数据类型或者类对象。

指向函数的指针包含了函数的地址,可以通过它来调用函数

函数指针就是指向函数的指针

int sum(int a,int b){
return a + b;
}
int mul(int a,int b){
return a * b;
}
//函数指针:指向函数的指针
int (*fun)(int, int);
int main(){
fun = sum;
cout << fun(100, 200) << endl;
fun = &mul;
cout << (*fun)(20, 30) << endl;
return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
例子

#include <iostream>
using namespace std;

int max(int x, int y){
 return x > y ? x : y;
}
int min(int a,int b){
 return a < b ? a : b;
}
int main(void){
 int (*p)(int, int) = max;
 int (*q)(int, int) = &min;
 cout<<(*p)(300, p(100, 200))<<endl;
 cout << q(99, (*q)(33, 77)) << endl;
}

可以连续调用

struct Data{
    int a;
    int b;
    Data(int a,int b):a(a),b(b){}
};
int col(Data x,Data y){
    return x.a + y.a+ x.b + y.b;
}
int main(void){
    Data aa(3, 4);
    Data bb(5, 6);
    //赋值的函数名,取不取地址都可以
    int (*point)(Data, Data) =col;//&cal
    //函数指针调用
    cout << point(aa, bb) << endl;
    cout << (*point)(bb, bb) << endl;
}

函数指针赋值,参数表类型必须和函数名类型匹配

int (*point)(Data, Data) =col;

千万不要加参数,因为指针赋值地址

函数指针可以当回调函数

函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。

说白了就是回调函数参数里面存在函数指针

把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,就叫做回调。
--如果代码立即被执行就称为同步回调;
--如果在之后晚点的某个时间再执行,则称为异步回调。
int add(int a,int b){
    return a + b;
}
int mul(int c,int d){
    return c * d;
}
void getNUm1(vector<int>& vec,int (*p)(int,int),int (*q)(int,int)){
    for (int i = 1; i < vec.size();i++){
        cout << p(vec[i], vec[i - 1]) << ",";
        cout << q(vec[i], vec[i - 1]) << endl;
    }
}
void getNUm2(vector<int>& vec,int (*p)(int,int),int (*q)(int,int)){
    for (int i = 1; i < vec.size();i++){
        cout << (*p)(vec[i], vec[i - 1]) << ",";
        cout << (*q)(vec[i], vec[i - 1]) << endl;
    }
}
int main(void){
    vector<int> vec = {1, 2, 3, 4, 5};
    getNUm1(vec, add, mul);
    getNUm2(vec, &add, &mul);
}

总结

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 指针函数:返回值是一个指针的函数
  • 函数指针:指向一个函数地址的指针

数组指针

一个指针指向一个数组

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

int main(void){
    int temp[6] = {1, 2, 3, 4, 5, 6};
    for (int i = 0; i < 6;i++){
        cout << *(temp + i) << "," << temp[i] << ",";
    }
    cout << endl;
    int *p = temp; //&temp[0]
    for (int i = 0; i < 6;i++){
        cout << *(p + i) << "," << p[i] << ",";
    }
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

 int a[5] = {10, 20, 30, 40, 50};
    int(*p)[5] = &a;//把数组a的地址赋给p,则p为数组a的地址
    for (int i = 0; i < 5;i++){
        cout << *(*p + i) << "," << (*p)[i] << endl;
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

指向二维数组

  int a[3][5] = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10},
        {11, 12, 13, 14, 15}};
    int(*p)[5] = a;//&a[0]
    for (int i = 0; i < 3;i++){
        for (int j = 0; j < 5;j++){
            cout << (*p)[j] <<" ";
        }
        cout << endl;
        ++p;
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里是把数组第一个元素赋值给p,因为二维数组在内存也是占一行的,不能赋值整个数组

int a[3][5] = {
        1, 2, 3, 4, 5,
        6, 7, 8, 9, 10,
        11, 12, 13, 14, 15};

&a[0]==&*(a+0)==a

注意p+1后,整个数组移动5个步长

二维数组的指向

int a[3][5] = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10},
        {11, 12, 13, 14, 15}};
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 5; j++){
            cout << a[i][j] << " ";
            cout << *(a[i] + j) << " ";
            cout << *(*(a + i) + j) << " ";
            cout << (*(a + i))[j] << " ";
        }
        cout << endl;
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


数组指针的行大小只要和数组吻合,可以把数组任意一行赋给它

利用:&a[i]或者a+i,都代表第i行

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

 int a[3][5] = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10},
        {11, 12, 13, 14, 15}};
    int(*q)[5] = a + 1;
    for (int i = 0; i < 5;i++){
        cout << (*q)[i] << " ";
    }
    cout << endl;
    int(*p)[5] = &a[2];
    for (int i = 0; i < 5;i++){
        cout <<*((*p)+i) << " ";
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


 int a[3][5] = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10},
        {11, 12, 13, 14, 15}};
    int(*p)[5] = a;
    for (int i = 0; i < 3;i++){
        for (int j = 0; j < 5;j++){
           cout << p[i][j] << ",";
           cout << (*(p+i))[j] << ",";
           cout << *(p[i]+j) << ",";
           cout << *(*(p+i)+j) << ",";
        }
        cout << endl;
    }

同样p [ i ] [ j ]可以访问到元素


 int a[3][5] = {
        {1, 2, 3, 4, 5},
        {6, 7, 8, 9, 10},
        {11, 12, 13, 14, 15}};
    int(*p)[5] = a+1;//指向了第二行
    for (int i = 0; i < 2;i++){
        for (int j = 0; j < 5;j++){
           //注意:(*())[j]的括号en不可省
           cout << (*(p+i))[j] << ",";
        }
        cout << endl;
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

指针数组

指针数组

一个由n个指针类型元素组成的指针数组,或者说这个当一个数组里含有的元素为指针类型的时候,它就被成为指针数组

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

int a=100;
    int b = 200;
    int c = 300;
    int *p[3];//数组类型为n指针
    p[0] = &a;
    p[1] = &b;
    p[2] = &c;
    for (int i = 0; i < 3;i++){
        cout << *p[i] << endl;
    }

p[i]是指针,所以*(p[i])才能取到值但是[]优先级更高,不必加括号

 int arr[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}};
    int *p[3];//指针数组
    for (int i = 0; i < 3;i++){
        cout << arr[i]<<","<<arr+i<<","<<*(arr+i) << endl;
        p[i] = arr[i];
    }
    for (int i = 0; i < 3;i++){
        for (int j = 0; j < 4;j++){
            cout << p[i][j] << ",";
        }
        cout << endl;
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

发现:arr[i]和arr+i和*(arr+i)都是表示的地址

同理:p[i] [j]可以写成等价的四种形式


    int a[3] = {1, 2, 3};
    int b[3] = {4, 5, 6};
    int c[3] = {7, 8, 9};
    int *p[3]; // 指针数组
    p[0] = a;
    p[1] = b;
    p[2] = &c[0];
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 3;j++){
            cout << *(p[i]+j) << ",";
        }
        cout << endl;
    }

扩展

   void test(const char* str)
{
      printf("%s\n", str);    
}
 int main( )
{
      //函数指针pfun
      void (*pfun) (const char*) = test;
     //函数指针的数组pfunArr
      void (*pfunArr[51)(const char* str); pfunArr[0] = test;
     //指向函数指针数组pfunArr的指针ppfunArr
      void (*(*ppfunArr)[10])(const char*) = &pfunArr;return 0;   

首先记住:

返回值 (*函数名)(含参表)一定是个函数指针

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有含参数表,在函数名内部写成:指针数组

上图是:指向函数的指针数组的指针

int Add(int x, int y) {
	return x + y;
} 
 
int main() {
	//函数指针
	int(*pAdd)(int, int) = Add;//&Add
	//函数指针的数组
	int (*pArr[5])(int, int);
    //指向函数指针数组的指针——基于函数指针的数组去写
	int (*(*ppArr)[5])(int, int)=&pArr;
	return 0;
}

用变量a给出如下定义:

*函数指针数组首先是个数组。这个数组(包含 6 个元素),每个元素都是一个函数指针。

int (*a[10])(int)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值