关于static的使用和函数中指针的一个认识误区

      在最初学习C语言函数时,我们就知道给函数传参有两种方法,一种是按值传递,另一种是按地址传递(传指针)。

以swap函数为例:

void swap(int a,int b){

    int temp=a;

    a=b;

    b=temp;

}

      对于两种传参方式,效果一目了然。按值是单向传递,对实参生成副本,不直接操作main函数中的参数,因此不会交换main函数中参数的值。而如果传指针,则直接对地址进行操作,能够改变main函数中的参数。这时,我总会认为,main函数调用swap,传递了地址,而swap也确实改变了参数的值,因此传递指针调用函数,应该是双向的,然而真的是这样的吗?


      在学习指针时,老师留了一个作业,调用函数,用指向指针的指针的方法对整数进行排序,并在main函数中输出排序后的整数。我们不去考虑这样写程序的实用性,仅仅是以应用学过的知识为目的去看这个代码,并从编程过程中遇到的问题来学习一些东西。


这是我最初写的代码:

#include <stdio.h>
#define N 100
int **pp;
void sort(int n,int *p){
pp=&p;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(*((*pp)+i)>*((*pp)+j)){
int temp=*((*pp)+i);
*((*pp)+i)=*((*pp)+j);
*((*pp)+j)=temp;
}
}
}
}
int main(){
int n;
int a[N];
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(n,a);
for(int i=0;i<n;i++){
printf("%d ",*((*pp)+i));
}
return 0;

}

调用函数时,用指针p指向实参a的地址,因为题设要求用指向指针的指针,所以声明pp指向p,而后操作pp进行排序。看似并没有什么问题,因为我在函数中直接操作的就是参数的地址,因此逻辑上没有问题。但是调试的时候,总会程序停止运行,那么问题出在哪了呢?就出在  printf("%d ",*((*pp)+i));  上了。

      对于赋值语句:pp=&p;  p确实指向了函数的地址,pp也确实指向了p的地址,而且pp也是全局变量,但是,p是在函数形参,在函数调用结束之后,就消失了,这时,pp指向的地址就不存在了,因此,在输出时会停止运行。

      通常,我总会认为p和a是一样的。实际上,a是一个地址常量,p是一个指向a的指针变量,在函数作用域内有效,函数并没有返还给main函数东西,因此实际上即使是按指针传递变量,仍然是单向传递的,只是函数作用于地址,改变了值。


那么对于这道题,怎么解决这个问题呢?关键就在让pp指向的值不失效,一个办法就是将p声明为static静态类型,这样就能不受函数限制而一直存在:


#include <stdio.h>
#define N 100
int **pp;
void sort(int n,int a[]){
static int *p=a;
pp=&p;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(*((*pp)+i)>*((*pp)+j)){
int temp=*((*pp)+i);
*((*pp)+i)=*((*pp)+j);
*((*pp)+j)=temp;
}
}
}
}
int main(){
int n;
int a[N];
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(n,a);
for(int i=0;i<n;i++){
printf("%d ",*((*pp)+i));
}
return 0;
}

      

猜你喜欢

转载自blog.csdn.net/BrightHao_zi/article/details/80456593