听翁恺老师mooc笔记(4)--指针的应用场景

听翁恺老师mooc笔记(4)--指针的应用场景

指针应用场景一:交换两个变量的值

在学习函数时,交换两个数的值,做一个swap函数,传递值进去,也可以将两个值交换过来,没问题,可是离开swap就没有用了,为什么?因为传进去的是两个值。

1 #include

2 void swap(int a,int b);

3

4 int main(void) {

5 int i=6;

6 int j=8;

7 swap(i,j);

8 printf("i=%d,j=%d\n",i,j);

9 return 0;

10 }

11

12 void swap(int a,int b){

13 int p;

14 p=a;

15 a=b;

16 b=p;

17 printf("a=%d,b=%d\n",a,b);

18 }

View Code

现在学过指针后,就可以用指针来交换变量了,传两个地址进去,试一下:

1 #include

2 void swap(int *pa,int *pb);

3

4 int main(void) {

5 int a=6;

6 int b=8;

7 swap(&a,&b);

8 printf("a=%d,b=%d\n",a,b);

9 return 0;

10 }

11

12 void swap(int *pa,int *pb){

13 int t;

14 t=*pa;

15 *pa=*pb;

16 *pb=t;

17 }

View Code

swap函数的参数是两个指针,在swap内部使用的都是*运算符,在main里将a,b的地址传递过去,运行我们发现值交换成功了。

指针应用场景二:函数通过指针返回多个值

在上面的例子中,swap函数在做交换后,返回来2个值,只返回a不够,还应该返回b。所以某些值就只能通过指针带回,也就是说传入的参数实际上是需要保存带回的结果的变量。再看一个例子:

1 #include

2 void minmax(int a[],int len,int *max,int *min);

3

4 int main(void) {

5 int a[]={1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55};

6 int min,max;

7 minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);

8 printf("min=%d,max=%d\n",min,max);

9 return 0;

10 }

11

12 void minmax(int a[],int len,int *min,int *max){

13 int i;

14 *min =*max=a[0];

15 for(i=1;i

16 if(a[i]<*min){

17 *min=a[i];

18 }

19 if(a[i]>*max){

20 *max=a[i];

21 }

22 }

23 }

View Code

minmax函数有4个参数,第一个参数a[]是数组,在这个参数中找出最大和最小的数组元素,第二个len是表示数组的长度,最后两个是*max和*min,minmax函数需要算出两个结果,最小值和最大值。两个结果不可能通过函数的返回值来获得,返回值只能返回一个,那么需要通过两个指针来返回两个结果。

在minmax函数中,首先使*min和*max等于a的第一个元素。然后使用for循环从第二个元素起遍历整个数组,如果发现某个元素比*min小了,就将该值赋值给*min。最后在main里调用minmax函数,使用sizeof函数得到数组的长度传递过去,然后将main里的int类型min和max取地址传递给minmax函数。查看下运行的结果,min是1,max是55.

这就是指针应用非常常见的一个场景,需要函数处理的结果不止一个,通过指针把要接受结果的变量的地址传递过去,然后在函数内部把这些变量的值填好,同时传递回来。所以虽然*min和*max是传递进去的参数,但是他们的作用是把值带出来。

指针应用场景二b:函数返回运算的状态,结果通过指针返回

函数在运算的过程中遇到一些特殊的状态,或者说在函数运算时没有得到正确的结果,常用的套路是什么那?是让函数返回特殊的不属于有效范围内的值来表示出错。在C语言的标准库里,和文件操作相关的函数里能看到大量的这样的例子,这些函数要么返回-1要么返回0来表示这个操作没有成功。如果当函数返回任何值都是有效的可能结果时,0或者-1也是属于有效的,就没有办法通过返回值来表示结果是否正确,这时需要分开返回:函数的状态通过返回值来返回,实际的值通过指针参数来返回。这样做的好处是,可以容易的将结果放在if语句里去,看下两个值做除法的例子:

1 #include

2 //return 如果除法成功,返回1;否则返回0

3 int divide(int a,int b,int *result);

4

5 int main(void) {

6 int a=5;

7 int b=2;

8 int c;

9 if(divide(a,b,&c)){

10 printf("%d/%d=%d\n",a,b,c);

11 }

12 return 0;

13 }

14

15 int divide(int a,int b,int *result){

16 int ret=1;

17 if(b==0) ret = 0;

18 else{

19 *result=a/b;

20 }

21 return ret;

22 }

View Code

divide函数有三个参数,整数a和整数b,a除以b的结果放在第三个参数*result中,函数的返回值是如果除法是成功的,则返回值返回1,如果除数是0,让返回值为0,程序就终止不去做除法运算了产生异常返回0.在main里,如果返回值是1,条件满足打印输出abc的结果,如果返回值是0,条件不满足,不打印,因为如果除数b为0,c里是不能产生任何有意义的值。

这种场景就是函数运算可能回出错,这种错误通过另外的场景表达出来,在c语言里只能这样。在后续的C++,java语言中,采用异常机制来解决这个问题。

指针最常见的错误:

初学者在学习指针时最长犯的错误是,定义来指针变量,还没有指向任何变量,就开始使用指针。比如:

int *p;

int k;

k=12;

*p=12;

首先定义*p,*p没有指向任何一个变量,这个时候定义k,为k赋值。然后*p不是相当于一个变量吗,也为*p赋值一个值。这是不可行的,为什么?因为在定义时,*p是空的,没有指向任何一个具体的变量,没有被赋予一个实际的值,这个时候给*p赋值12,这个时候会发生的什么情况那,首先所有的本地变量都不会有默认的初始值,如果没有赋值就不会是个明确的值,可能是个乱七八糟的值,如果把这个乱七八糟的值当成一个地址的时候,p可能会指向一个莫名其妙的地方,所以当*p=12时,则就是把这个莫名其妙的地方写入12,但这个莫名其妙的地方恰巧是不可写的,这个时候程序就会崩溃。

试一下,如果int *p=0,让*p指向一个明确的不应该去的地方,这个时候程序可能就会出现一个段错误(和编译器有关),也可能编译可以过去,但是运行时结果出现问题,另外如果*p不赋值,同样可能编译能够过去,但是总有一天会出错,你不能保证*p里不指向一个不可写或者不存在的地方。这两种情况,在devc++环境下,都是编译可过,运行时出现错误:

相关推荐

dnf希洛克多久刷新
365betasia

dnf希洛克多久刷新

📅 08-19 👁️ 3649
熊猫金鱼多少钱一条?了解市场价格和养殖技巧
be365备用网址

熊猫金鱼多少钱一条?了解市场价格和养殖技巧

📅 08-31 👁️ 1654
苹果6s充满待机多长时间才是正常的?(刚买还没满一年)
365bet手机客户端首页

苹果6s充满待机多长时间才是正常的?(刚买还没满一年)

📅 07-23 👁️ 9253
宝马5系升级音响多少钱
365betasia

宝马5系升级音响多少钱

📅 08-30 👁️ 9350
中国人民解放军战区
365betasia

中国人民解放军战区

📅 07-16 👁️ 4575
月季花掉叶子补救方法
be365备用网址

月季花掉叶子补救方法

📅 08-03 👁️ 439