本篇继续深入介绍C语言指针的基本概念与知识点,以经典指针程序--------”互换两个数字“进行阐述,基础不牢地动山摇,有关指针的基础概念,需要提前学习的,可以通过链接跳转至第一、第二篇。
C语言指针入门学习、概念梳理(一)
C语言指针入门学习、概念梳理(二)
C语言指针入门学习、知识点梳理(三)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
首先看一个经典程序 : ”互换两个数字“
# include <stdio.h>
//不能完成互换功能
void exchange_1(int a, int b) //形参接收的是值,而不是a,b的地址,实参和形参互不影响,简单来说,
//此处括号中及子函数中的形参a,b可以改成其他任意字符,如x,y效果是一样的。
{
int t;
t = a; //此处的a,b与exchange_1()括号中的a,b是同一个
a = b;
b = t;
return; //经过exchange_1函数后,修改了形参a,b 的值,但不影响main函数中实参a,b的值,所以输出还是a = 3,b = 5
}
int main(void)
{
int a = 3; //实参
int b = 5;
exchange_1(a,b); //此处括号的a,b与main函数定义的a,b相同,实参单向传给形参
printf("a = %d, b = %d\n", a,b);
//exchange_1函数中的形参a,b与 main主函数中的实参a,b不是同一个a,b
}
---------------------------------------------------------------------------------------------------------------------------------
运行结果: a = 3, b = 5 //想想为什么?为什么没有交换数值?
经过main主函数exchange_1(a.b)后,实参a,b将数值3,5传递给形参,进入交换子函数后,在函数内部完成了交换,
随后形参a,b的空间释放,而实参空间未释放,仍是a = 3,b = 5 ,故未达成互换目的。
形参交换了数据,而实参保持原数据不变,这是单向的实参到形参的传递过程,所以形参的值改变后实参的值没变,
形参在函数中是变量名,在函数调用时,形参被临时分配相应的内存。调用结束后,形参单元被释放,而实参单元保留并维持原值。
运行结果是 3,5 还是 5, 3 ?首先要知道,局部变量执行完就释放了,达不到置换效果。main函数中的局部变量a,b,只在本函数使用,所以与exchange_1函数中的a,b不冲突,如果结果是a = 5,b = 3意味着exchange_1把main函数中的a,b改写了;如果结果还是a = 3 , b = 5意味着调用完exchange_1函数后,a,b的值照样没有改变。
若要使其数值交换,需要如何更改呢?
1.在调用子函数更改数值后,在子函数结束,释放形参空间前将结果输出打印出来,另外在主函数中输出打印a,b,测试实参a,b是否被修改
# include <stdio.h>
//不能完成互换功能
void exchange_1(int x, int y) //形参与实参互不影响,因此与使用什么符号无关
{
int t;
t = x; //此处的a,b与exchange_1()括号中的a,b是同一个
x = y;
y = t;
printf("a = %d,b = %d\n", x,y); //形参交换成功,在函数结束,释放形参前将结果打印输出
return;
}
int main(void)
{
int a = 3; //实参
int b = 5;
exchange_1(a,b); //此处括号的a,b与main函数定义的a,b相同,实参单向传给形参x,y
printf("a = %d,b = %d\n", a,b); //参照组,看看实参a,b的值是否被更改
}
------------------------------------------------------------------------------------------------------------------------------
运行结果 :
a = 5,b = 3
a = 3,b = 5
结果表明,形参与实参互不影响,形参交换成功,实参未能交换,因为函数调用结束形参将被释放,主函数中实参值不变。
2. 使用指针------错误用法
# include <stdio.h>
//不能完成互换功能
void exchange_2(int * p, int * q) //此处指针变量是p, int *是数据类型,指针变量p必须接收同类型的变量地址
{
// int t; //error:错误,t = p类型不一致,p是指针变量,t也必须是同类型变量
int * t; //若要互换p、q的值,t必须是int *类型,不能是int类型
t = p;
p = q;
q = t;
return;
}
int main(void)
{
int a = 3;
int b = 5;
//exchange_2(*p, *q); //error: 错误,形参中指针变量p必须接收同类型的便利地址,*p,*q不是变量地址。
//exchange_2(a, b); //error: 错误,理由同上
exchange_2(&a, &b); //正确,&a, &b都是整型变量地址,传递给整型指针变量p
printf("a = %d, b = %d\n", a, b); //对于a,b来说,值和地址都没变,换的是p,q存储的内容。
return 0;
}
------------------------------------------------------------------------------------------------------------------------------
运行结果: a = 3, b = 5
1.不要把p,q看成是指针,单纯看成变量,调用函数时传入的不是a,b而是a,b的值,相当于把a,b的值拷贝了一份传递给p,q, 子函数怎么玩都是p,q的值,而不是a,b本身,形参的改变不影响实参。
2.p是地址,*p是值,p和q的地址互换并不影响a,b ,a,b的地址和值并没有改变, 通俗来讲就是:a,b分别住在两间房中,p,q把门牌号互换了,但a,b还各自躺在原来的房间里,房间相对于走廊的地址并没有变(如a开始是在二楼第一间,互换门牌号后还是在二楼第一间)。
3.使用指针------正确用法:
# include <stdio.h>
//能完成互换功能
void exchange_3(int * p, int * q) //此处指针变量是p, int *是数据类型,指针变量p必须接收同类型的变量地址
{
int t; //若要互换*p、*q的值,t的类型要与*p,*q一致,即int整型,不能定义成int * 否则语法会错误
t = *p; //*p代表的是以p的内容为地址的变量,p存放整型地址,则*p代表整型变量,所以*p是int整型,即t也要是整型int t;
*p = *q; //*p就是a, *q就是b,所以互换的不是q,p的值,此函数将a,b的值给改了,完成了交换
*q = t; //这里的*p,*q在全局整个程序中都是等同于a, b的,所以*p,*q地址和值都已改变,成功交换主函数中的a,b
return;
}
int main(void)
{
int a = 3;
int b = 5;
exchange_3(&a, &b); //正确,&a, &b都是整型变量地址,传递给整型指针变量p
printf("a = %d, b = %d\n", a, b); //对于a,b来说,值和地址都没变,换的是p,q存储的内容。
return 0;
}
-------------------------------------------------------------------------------------------------------------------------
运行结果: a = 5, b = 3
这里的*p,*q在全局整个程序中都是等同于a, b的,所以*p,*q地址和值都已交换,所以等价于a,b交换。
仔细观察exchange_1()、exchange_2()、exchange_3()的相同与不同之处,为何只有3才能交换成功。
因为
exchange_1()只改变形参,实参地址与值没变,交换失败;
exchange_2()只交换形参地址,不影响实参,交换失败;
exchange_3()交换*p,*q地址和数值都交换了,且二者分别等同于a,b,故交换成功。
(本人能力有限,博客仅供广大网友参考学习,若有不足之处,还望指正,共同进步!)