一、使用指针作为参数,可以实现两种功能:
(1)可以读取上一层函数中的变量的值*p
(2)可以修改上一层函数中变量中的值*p(普通参数无法实现)
#include<stdio.h>
void test(int* p){
printf("内层a:%d \n",*p);//读取上一层参数的值
*p=1;//修改上一层参数的值
}
int main(){
int a=0;
test(&a);
printf("外层a:%d \n",a);
return 0;
}
二、应用
1.1使用指针交换两个参数
#include<stdio.h>
void swap(int* p1,int* p2){
int t;
t=*p1;//取a的值付给t
*p1=*p2;//b的值赋给a
*p2=t;//将a的值赋给b
}
int main(){
int a=10;
int b=50;
printf("Before swap a:%d b:%d\n",a,b);// 10 50
swap(&a,&b);
printf("After swap a:%d b:%d\n",a,b); //50 10
return 0;
}
如上图所示,a和p1指向同一个内存地址,b和p2指向同一个内存地址。
将p1和p2指向的内存地址的值交换,同时就改变了a、b指向的内存地址对应的值,因此成功实现了值交换。
1.2错误用例
#include<stdio.h>
void swap(int* p1,int* p2){
int *p_temp;
p_temp = p1;
p1 = p2;
p2 = p_temp;
printf("After swap p1:%d p2:%d\n",p1,p2);
}
int main(){
int a=10;
int b=50;
printf("before swap a :%d b :%d\n",&a,&b);
swap(&a,&b);
printf("After swap a :%d b :%d\n",&a,&b);
return 0;
}
如上图所示,a和p1指向同一个内存地址,b和p2指向同一个内存地址。
将p1和p2指向的内存地址交换,不改变a、b指向的内存地址对应的值,因此值交换失败。
2传递数组作为参数
2.1数组名实质是一个指针类型,传递数组,就是传递指针。
传递数组时,总是要另外传递长度信息。
int avg(int *p,int len){
}
或
int avg(int p[],int len){//等价,传递一个元素以上
}
把数组信息传给一个函数:
(1)首地址:一片连续内存地址
(2)长度:这块内存上存储的对象的个数
2.1.1实例:计算指定长度的数组元素平均值
#include<stdio.h>
int avg(int* p,int len){
int sum=0;
for(int i=0;i<len;i++){
sum+=p[i];
}
return sum/len;
}
int main(){
int arr[5]={1,2,3,4,5};
int ret=avg(arr,3);//传递arr[0]~arr[2]
printf("%d\n",ret);//2
return 0;
}
对于avg而言,不关心你是不是叫“数组”,在它眼中,它只接收到一个内存地址而已。
3传指针可以返回多个值
#include<stdio.h>
void max_min(int *p,int len,int* pmax,int* pmin){
int x=p[0];
int n=p[0];
for(int i=1;i<len;i++){
if(x<p[i])
x=p[i];
if(n>p[i])
n=p[i];
}
*pmax=x;
*pmin=n;
}
int main(){
int arr[10]={12,55,44,98,24,545,-12,0,-9,2};
int max;//定义为整数类型,而不是指针类型
int min;
max_min(arr,10,&max,&min);//一定不要忘了&
printf("%d %d",max,min);
return 0;
}
三、传指针有什么用?(效率问题)
传值和传地址 传值和传引用
传值相当于传递一个拷贝,占用空间,复制元素占用时间,而传地址,只需传一次地址就可以了,可以直接访问。
对于变量所占空间大的适合传地址。
四、总结
1学会把变量的地址传给函数
2学会把数组信息传递给函数,传数组时必须要长度信息
3用指针作为输出参数,返回多个值
4明白“传值”和“传地址”的区别,及效率上的差异。