boot 发表于 2017-9-26 09:31:14

指针变量做形参 排序


我打算用指针变量为形参,进行三个数从小到大的排序。
但是在我调试的时候,发现在swap函数里地址是交换成功的,
可是一回到compare函数里,地址用变回原来的样子了。
希望大家给我这个小白一点建议,谢谢{:10_254:}

#include "stdio.h"

void main()
{
      int a, b, c;
      int *A, *B, *C;
      void compare(int *x, int *y, int *z);
      
      printf("please input a, b, c\n");
      scanf("%d %d %d", &a, &b, &c);
      A = &a;
      B = &b;
      C = &c;
      compare(A, B, C);
}

void compare(int *x, int *y, int *z)
{
      void swap(int *x, int *y);
      
      if(*x > *y)
      {
            swap(x, y);
      }
      if(*x > *z)
      {
            swap(x, z);
      }
      if(*y > *z)
      {
            swap(y, z);
      }      
      printf("%d < %d < %d\n", *x, *y, *z);
}

void swap(int *x, int *y)
{
      int *temp;
      
      temp = x;
      x = y;
      y = temp;   
}


丶忘却的年少o 发表于 2017-9-26 09:37:36

swap的参数应该是指向指针的指针,因为你要改变指针自身的指向。
把调用这个函数的实参前加个&
void swap(int **x, int **y)
{
      int *temp;
      
      temp = *x;
      *x = *y;
      *y = temp;   
}

boot 发表于 2017-9-26 12:31:09

丶忘却的年少o 发表于 2017-9-26 09:37
swap的参数应该是指向指针的指针,因为你要改变指针自身的指向。
把调用这个函数的实参前加个&

谢谢大神, 不过我实参前面没加“&”也可以啊

丶忘却的年少o 发表于 2017-9-26 12:47:27

boot 发表于 2017-9-26 12:31
谢谢大神, 不过我实参前面没加“&”也可以啊

可以是可以,但是你后面swap函数里就是交换值,就是a b c对应的值交换了。要是实参前加了就是交换指针指向,不改变值。你可以在main最后加一条          printf("a = %db = %dc = %d\n", a, b, c); 看看,值应该是换掉了

boot 发表于 2017-9-26 12:52:35

丶忘却的年少o 发表于 2017-9-26 12:47
可以是可以,但是你后面swap函数里就是交换值,就是a b c对应的值交换了。要是实参前加了就是交换指针指 ...

对对对,谢谢你了

丶忘却的年少o 发表于 2017-9-26 12:59:24

boot 发表于 2017-9-26 12:52
对对对,谢谢你了

不客气,忘记说了,传过去的参数是有代码段作用域,只在那个函数里变化有用,返回到调用函数里失效了,这就是为什么你的swap里变化了返回后没变化,用指针就不会。
指针是个比较复杂麻烦的东西,懂了后就很好用,慢慢学,加油

boot 发表于 2017-9-26 13:09:08

丶忘却的年少o 发表于 2017-9-26 12:59
不客气,忘记说了,传过去的参数是有代码段作用域,只在那个函数里变化有用,返回到调用函数里失效了,这 ...

好的,我会加油的{:10_279:}

boot 发表于 2017-9-27 13:06:41

丶忘却的年少o 发表于 2017-9-26 12:59
不客气,忘记说了,传过去的参数是有代码段作用域,只在那个函数里变化有用,返回到调用函数里失效了,这 ...

大神,你能讲解一下这个过程原理是如何进行的,指针的地址变换了为什么指针指向的值也变了?

丶忘却的年少o 发表于 2017-9-27 13:26:05

boot 发表于 2017-9-27 13:06
大神,你能讲解一下这个过程原理是如何进行的,指针的地址变换了为什么指针指向的值也变了?

不是指针的地址变了,是指针存放的地址(指向的地址)变了,指针指向的值当然是变了。
先说下你一开始的程序,你的理解是对的,但是参数只有代码段作用域,你要是在swap里printf变化后的值肯定是对的,就是你要的。但是没返回呀,在这个函数里的东西就会随着函数的结束都释放了,回到调用函数就是调用函数本身应该有的值。所以要把指针的地址传过去,让被调用的函数改变这个指针存放的地址,就是改变指针指向的地址,让它指向一个你要的数的地址。不懂没关系,看下面↓
本来*p指向a,*p1指向b,指针*p、*p1存的是a、b的地址。那我用指向指针的指针**p2、**p3分别指向*p、*p1,为了方便你理解,我们把*p、*p1看成一个数,不是指针,等价的*p2、*p3分别指向p、p1,我要改变p、p1的值是不是改变*p2、*p3(这里的*是取值的意思)就可以实现,用一个临时变量,让他们互换,是不是p、p1就互换了值。好,现在扔掉**p2、**p3,我们来看*p、*p1,现在对他们取值是不是也互换了,因为他们指向的地址互换了。

boot 发表于 2017-9-27 20:21:34

丶忘却的年少o 发表于 2017-9-27 13:26
不是指针的地址变了,是指针存放的地址(指向的地址)变了,指针指向的值当然是变了。
先说下你一开始的 ...

谢谢啦,看了你的分析我懂了一点。但还是有几个地方还是有点不明白。
按照你说的(不清楚对不对哈{:10_282:}):
p = &a;       p1 = &b; (*p指向a,*p1指向b)
p2 = &p;   p3 = &p1; (指向指针的指针**p2、**p3分别指向*p、*p1)
“我们把*p、*p1看成一个数,不是指针”你的意思是p、p1存放的地址看作是数,对吧?
然后你说“等价的*p2、*p3分别指向p、p1”,这里的p1、p是什么???(你说*p、*p1是指针,这里p、p1没有“*”)

丶忘却的年少o 发表于 2017-9-27 20:45:09

boot 发表于 2017-9-27 20:21
谢谢啦,看了你的分析我懂了一点。但还是有几个地方还是有点不明白。
按照你说的(不清楚对不对哈{:10_28 ...

对呀,你要把那两句连起来看嘛,你理解的没错的,p、p1存放的地址看作是数,就是p = (a的地址),p1 = (b的地址)。就是分别降一级指针,指针变成常数,指向指针的指针变成指针就好了(这个按照指针原理来是不科学的,我这么说是为了让你理解,你要是理解了就忘记了吧)。那p2、p3就是指针,而p、p1就是常数,既然是常数,就不要*了,然后接着我说的,接下去看,用临时变量来当中间值互换指针p2、p3的值那是不是就相当于p、p1的互换(别考虑别的因素,因为二次指针自己有限制的,就跟着这个思路走)。然后还原p、p1指针,指向的就是指向的a、b了

丶忘却的年少o 发表于 2017-9-27 20:56:10

如果还是要考虑指针等价后的因素问题,我换一种说法(比较符合原理):
**p2 = *p = &a,   **p3= *p1 = &b
对**p2和 **p3进行指向操作:*p2 = p, *p3 = p1
temp = *p2, *p2 = *p3, *p3 = temp等价于
temp = p, p = p1, p1 = temp此时的p和p1结果就是
**p2 = *p = &b,   **p3= *p1 = &a

boot 发表于 2017-9-27 21:13:19

哦哦,太感谢了,明白了{:10_297:}
页: [1]
查看完整版本: 指针变量做形参 排序