C++的指针与函数
- 引言
- 一、指针变量作为函数的参数
- 1.1、单向传递:值传递
- 1.2、单向传递:传地址
- 二、数组作为函数的参数传递
- 三、函数的返回值类型是指针类型
- 四、函数指针
- 4.1、函数指针的定义
- 4.2、函数指针变量的注意事项
- 4.3、函数指针变量使用typedef定义别名
- 4.4、函数指针作为函数的参数
- 总结
引言
💡 作者简介:专注于C/C++高性能程序设计和开发,理论与代码实践结合,让世界没有难学的技术。包括C/C++、Linux、MySQL、Redis、TCP/IP、协程、网络编程等。
👉
🎖️ CSDN实力新星,社区专家博主
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu
🔔 上一篇:【018】C++的指针数组和数组指针
一、指针变量作为函数的参数
如果想在函数内部修改外部变量的值,需要将外部变量的地址传递给函数。
1.1、单向传递:值传递
函数内部不能修改外部变量的值。
#include <iostream>
using namespace std;
void set(int num2)// 相当于 int num2=num;
{
num2=10;
}
int main()
{
int num=1;
set(num);
cout<<"num = "<<num<<endl;
return 0;
}
输出:
num = 1
1.2、单向传递:传地址
函数内部可以修改外部变量的值。
#include <iostream>
using namespace std;
void set(int *p)// 相当于 int *p=#
{
*p=10;
}
int main()
{
int num=1;
set(num);
cout<<"num = "<<num<<endl;
return 0;
}
输出:
num = 10
二、数组作为函数的参数传递
函数内部想操作外部数组元素,将数组名传递给函数。
- 一维数组作为函数的参数,会被编译器优化为指针变量。
- 二维数组作为函数的形参会被优化成一维数组指针。
(1)一维数组作为函数的参数传递:
#include <iostream>
using namespace std;
void foreach(int p[5])//优化成void foreach(int *arr)
{
cout<<"sizeof(p) = "<<sizeof(p)<<endl;
//遍历
for(int i=0;i<5;i++)
{
cout<<p[i]<<" ";
}
cout<<endl;
}
int main()
{
int num[5]={1,2,3,4,5};
cout<<"sizeof(num) = "<<sizeof(num)<<endl;
foreach(num);
return 0;
}
输出:
sizeof(num) = 20
sizeof(p) = 4
1 2 3 4 5
(2)二维数组作为函数的参数传递:
#include <iostream>
using namespace std;
// void foreach(int (*p)[4],int row,int col)和下面的等价
void foreach(int p[3][4],int row,int col)
{
cout<<"sizeof(p) = "<<sizeof(p)<<endl;
//遍历
for(int i=0;i<col;i++)
{
for(int j=0;j<col;j++)
cout<<p[i][j]<<" ";
cout<<endl;
}
cout<<endl;
}
int main()
{
int num[3][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
cout<<"sizeof(num) = "<<sizeof(num)<<endl;
foreach(num,sizeof(num)/sizeof(num[0]),sizeof(num[0])/sizeof(num[0][0]));
return 0;
}
输出:
sizeof(num) = 48
sizeof(p) = 4
1 2 3 4
5 6 7 8
9 10 11 12
三、函数的返回值类型是指针类型
将函数内部的合法地址通过返回值返回给函数外部使用。
注意:函数不要返回普通局部变量的地址,返回普通局部变量的地址会出现段错误,使用一个已经释放的内存空间的行为是未定义的。但是,可以返回静态变量的地址,因为静态变量的生命周期是整个进程,所以是一个合法的地址。
#include <iostream>
using namespace std;
int* test()
{
// int data=1;
// return &data;
static data=2;
return &data;
}
int main()
{
int *p=test();
cout<<"test return "<<*p<<endl;// 输出2
return 0;
}
四、函数指针
4.1、函数指针的定义
函数名代表函数的入口地址。函数指针本质上是一个指针变量,只是该变量保存的是函数的入口地址。
#include <iostream>
using namespace std;
int add(int x, int y)
{
return x+y;
}
int main()
{
// 函数指针
int (*p)(int,int)=NULL;
cout<<"sizeof(p) = "<<sizeof(p)<<endl;// 输出4
// 函数指针与函数入口建立关系
p=add;
// 通过函数指针调用函数
cout<<p(1,2)<<endl;//输出3
return 0;
}
4.2、函数指针变量的注意事项
- 函数指针变量不要加1操作,没有意义。
- 不要对函数指针变量取*,没有意义,编译器会自动优化。
- 函数指针变量判断大小也没有意义。
- 函数指针变量可以赋值,比如:p1=p2。
- 函数指针变量可以判断相等,比如:p1==P2。
4.3、函数指针变量使用typedef定义别名
#include <iostream>
using namespace std;
int add(int x, int y)
{
return x+y;
}
typedef int (*FUNC_NAME)(int,int);
int main()
{
// 函数指针
FUNC_NAME p =NULL;
cout<<"sizeof(p) = "<<sizeof(p)<<endl;// 输出4
// 函数指针与函数入口建立关系
p=add;
// 通过函数指针调用函数
cout<<p(1,2)<<endl;//输出3
return 0;
}
4.4、函数指针作为函数的参数
目的:让算法功能多样化,更加强大。
#include <iostream>
using namespace std;
int add(int x, int y)
{
return x+y;
}
int sub(int x, int y)
{
return x-y;
}
int mul(int x, int y)
{
return x*y;
}
int div(int x, int y)
{
return x/y;
}
int myCalc(int x,int y,int (*func)(int,int))
{
return func(x,y);
}
int main()
{
cout<<myCalc(20,30,add)<<endl;
cout<<myCalc(20,30,sub)<<endl;
cout<<myCalc(20,30,mul)<<endl;
cout<<myCalc(20,30,div)<<endl;
return 0;
}
总结
C++中指针和函数有着紧密的联系,指针可以用来存储函数的地址,通过指针调用函数或者将函数作为参数传递给其他函数。
- 如何定义一个函数指针?
定义一个函数指针需要声明一个与被调用函数相同返回类型和参数列表的指针类型,例如:
int (*func_ptr)(int, int); // 定义了一个接受两个整型参数并返回整型结果的函数指针
- 如何将函数地址赋值给指针?
可以使用取地址符号&
获取函数地址,并将其赋值给对应类型的指针变量,例如:
int add(int a, int b) { return a + b; }
int (*func_ptr)(int, int) = &add; // 将add()的地址赋值给func_ptr
- 如何通过函数指针调用对应的函数?
可以使用解引用运算符*
或者直接使用函数名加括号()
进行调用,例如:
int result = (*func_ptr)(1, 2); // 使用解引用运算符进行调用
int result2 = func_ptr(1, 2); // 直接使用函数名进行调用(会隐式地转换成解引用)
- 如何在其他函数中传递一个包含参数为函数指针的形参?
可以将该形参声明为一个带有函数指针类型参数的函数,例如:
void operate(int a, int b, int (*func_ptr)(int, int)) {
// func_ptr 接收两个整型参数并返回整型结果的函数指针
int result = func_ptr(a, b);
cout << "The result is: " << result << endl;
}
int add(int a, int b) { return a + b; }
operate(1, 2, &add); // 调用 operate() 函数,并将 add() 函数地址传递给 func_ptr 形参
- 如何使用typedef为函数指针类型定义别名?
可以使用typedef
为复杂的函数指针类型定义别名,简化代码,例如:
typedef int (*CalcFuncPtr)(int, int); // 定义一个 CalcFuncPtr 类型为接受两个整数并返回整数的函数指针
int add(int a, int b) { return a + b; }
CalcFuncPtr func_ptr = &add; // 使用别名定义一个 CalcFuncPtr 类型的变量
int result = func_ptr(1, 2); // 直接调用该变量即可