指针
指针函数
指针函数一个函数,只不过这个函数的返回值是一个地址值
和普通函数唯一的区别就是在函数名前面多了一个*号
函数返回值必须用同类型的指针变量来接受
也可以将其返回值定义为
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( )
{//函数指针pfunvoid (*pfun) (const char*) = test;//函数指针的数组pfunArrvoid (*pfunArr[51)(const char* str); pfunArr[0] = test;//指向函数指针数组pfunArr的指针ppfunArrvoid (*(*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)