编写一个函数,在一个整型数组中查找某个指定的元素,若找到,则函数返回真,并把该数组元素的地址从一个参数中返回给调用者;否则,函数返回假。bool find(int key,int x[],int num,int *p)
{ int i=0;
while (i < num)
{ if (x[i] == key) 
{ p = &x[i];
return true;
    }
    i++;
}
return false;
}
void main()
{ int a[20],*q;
  ......
  q = a; 
  if (find(12,a,20,q) == true)
cout << q << endl;
  else
    cout << "not found" << endl;
}上述函数find是否正确?

正确的find的写法是:bool find(int key,int x[],int num,int **p)
{ int i=0;
while (i < num)
{ if (x[i] == key) 
{ *p = &x[i];
return true;
    }
    i++;
}
return false;
}
void main()
{ int a[20],*q;
  ......
  if (find(12,a,20,&q) == true)
cout << q << endl;
  else
    cout << "not found" << endl;
}
为什么后者正确而前者不对,100分送上,谢谢!!

解决方案 »

  1.   

    因为在函数内部修改形参是无法影响实参的。要直接影响实参只有两种方法:1,用引用
    bool find(int key,int x[],int num,int*& p)
    {
       ...
       p = &x[i];
       ...
    }2, 用指针bool find(int key,int x[],int num,int** p)
    {
       ...
       *p = &x[i];
       ...
    }
      

  2.   


    参数的传递是按值进行的,前一个例子调用函数之后并不能改变q的值,后一个例子传递了q的地址,所以可以改变q本身的值。
      

  3.   

    *p = &x[i]; 后者是个地址,前者是指针的引用,也就是说,赋值后p指向的指针*p现在指向正确的地址.简单的例子:你要改变 long l 的值,因为参数传递的是值,如果如下使用,虽然在函数体内值发生了改变,但那已经是复制的对象了void f(long l)
    {
         l  = 1000;
    }所以你只能把地址传给函数,如下:
    void f2(long * pl)
    {
        *pl  = 1000;
    }
    通过*,把pl这个地址保存的值改为1000而你要改变的是指针,自然要再加一次取地址
    void f3 (long **p)
    {
        long newl = 1000;
        long * pn = &newl;
        *p       = pn; 
    }简单的理解方法,你可以认为(*p) 就是一个long
      

  4.   

    编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p(指向同一个地址)。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在前一个函数中p = &x[i];只是_p的指向变了,但是p指向的地址未变.在后面的函数中,_p = p(指向同一个地址),*p = &x[i];即 *_p=&x[i];*_p的指向变了(修改了_p的内容),从而*p的指向也变了!(因为如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改),从而p的指向(没变)的指向变了!
    说得我也晕了,但是感觉清楚了,不知道你看的懂不?
      

  5.   

    参数的值在函数调用前后是不会变的
    除非你传递的是地址,你可以改变该地址指向的值,而非该地址的值
    现在你想返回地址,所以要传递地址的地址,也就是**p了。
    *p的值不会变,**p可以改写
      

  6.   

    虽然你第一次调用函数时P是为一个指针,但在执行 P= &x[i];时,只是把 x[i] 的地址赋给P,
    而在调用结束后,P还是恢复原来的a的地址,因为这个时候的 P 仍是一个作为存储地址的变量,
    在函数调用中仍被当作是传值调用, 在第二次调用中便被当成是传址调用了.