指针
指针函数
指针函数一个函数,只不过这个函数的返回值是一个地址值
和普通函数唯一的区别就是在函数名前面多了一个*号
函数返回值必须用同类型的指针变量来接受
也可以将其返回值定义为
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)