4.5 数组作为函数参数的易错点解析
对于函数调用过程中数组的使用,最常用的方式是把数组作为参数进行传递。下面通过一段代码来了解数组在函数调用中的使用,此段代码的功能为产生8个0~99之间的随机整数,这里采用冒泡法升级排序输出。
include<stdio.h>
include<stdlib.h>
define N 8
void sort(int arr[],int n)
{
int i,j;
int temp;
int flag;
for(i=0;i<n-1;i++)
{
flag=1;
for(j=0;j<n-i-1;j++)
{
if(arr[j]>arr[j+1])
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
flag=0;
}
}
}
for(i=0;i<n;i++)
{
printf("%d\t",arr[i]);
}
return;
}
int main(void)
{
int i;
int arr[N];
printf("排序前:\n");
for(i=0;i<N;i++)
{
arr[i]=rand()%100;
printf("%d\t",arr[i]);
}
printf("\n排序后:\n");
sort(arr,N);
return 0;
}
运行结果:
排序前:
41 67 34 0 69 24 78 58
排序后:
0 24 34 41 58 67 69 78
在sort()函数中,我们将main()函数中随机生成的数组通过参数传递给sort()函数,然后在sort()函数中对传递过去的数组元素进行排序。但是在使用数组名作为参数进行传递时需要注意,传递的是数组的首地址,即在函数sort()中操作的数组与在main()函数中定义的数组共享一个存储空间,所以在sort()函数中对arr数组元素进行排序也就是对在main()函数中定义的数组元素进行排序,所以也可以在main()函数中执行打印arr数组元素的操作,得到的同样是进行排序之后的数组,例如:
include<stdio.h>
include<stdlib.h>
define N 8
void sort(int arr[],int n)
{
int i,j;
int temp;
int flag;
for(i=0;i<n-1;i++)
{
flag=1;
for(j=0;j<n-i-1;j++)
{
if(arr[j]>arr[j+1])
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
flag=0;
}
}
}
return;
}
void print(int arr[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%d\t",arr[i]);
}
}
int main(void)
{
int i;
int arr[N];
printf("排序前:\n");
for(i=0;i<N;i++)
{
arr[i]=rand()%100;
printf("%d\t",arr[i]);
}
sort(arr,N);
printf("\n排序后:\n");
print(arr,N);
return 0;
}
运行结果:
排序前:
41 67 34 0 69 24 78 58
排序后:
0 24 34 41 58 67 69 78
从运行结果可以发现,这样的操作能够返回想要的结果。但是如果在一个函数中生成了一个数组,那么这个数组能否在其他函数中使用呢?看看下面的代码。
include<stdio.h>
include<stdlib.h>
define N 8
int*creat()
{
int i;
printf("creat()函数中产生数组元素\n");
int arr[N];
for(i=0;i<N;i++)
{
arr[i]=rand()%100;
printf("%d\t",arr[i]);
}
return arr;
}
void print(int arr[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%d\t",arr[i]);
}
}
int main(void)
{
int i;
int*p;
p=creat();
printf("\n通过函数调用返回后得到的数组\n");
print(p,N);
return 0;
}
运行结果:
creat()函数中产生数组元素
41 67 34 0 69 24 78 58
通过函数调用返回后得到的数组
-858993460-858993460-858993460-858993460-858993460
-858993460 6 1245056
上面的运行结果表明,函数并没有成功地返回想要的数组元素,这是因为在creat()函数中定义的数组arr在creat()函数调用结束后被自动释放掉了,所以不可能得到正确的结果。正如前面讲解的,数组arr的生存周期随着函数调用的结束而结束了,那么有什么办法能够成功地从数组中返回一个数组呢?当然是想办法使数组在函数调用结束之后不被释放。具体实现方法有以下两种。
将数组定义为静态数组。静态数组的定义与普通数组的定义的区别就在于要在数组的前面加上关键字static,例如:
include<stdio.h>
include<stdlib.h>
define N 8
int*creat()
{
int i;
printf("creat()函数中产生数组元素\n");
static int arr[N];
for(i=0;i<N;i++)
{
arr[i]=rand()%100;
printf("%d\t",arr[i]);
}
return arr;
}
void print(int arr[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%d\t",arr[i]);
}
}
int main(void)
{
int i;
int*p;
p=creat();
printf("\n通过函数调用返回后得到的数组\n");
print(p,N);
return 0;
}
运行结果:
creat()函数中产生数组元素
41 67 34 0 69 24 78 58
通过函数调用返回后得到的数组
41 67 34 0 69 24 78 58
定义为静态数组后发现成功返回了数组,这是因为静态数组的生存周期是从程序开始运行到程序运行结束,而不像普通数组那样随着函数调用的结束而结束其生命周期,所以数组不会随着函数调用的结束而被释放掉。
申请一个动态数组。对动态数组不了解的读者,可以先学习本书第4.6节的知识点,下面学习具体实现方法。
include<stdio.h>
include<stdlib.h>
define N 8
int*creat()
{
int i;
printf("creat()函数中产生数组元素\n");
intarr=(int)malloc(sizeof(int)N);
for(i=0;i<N;i++)
{
arr[i]=rand()%100;
printf("%d\t",arr[i]);
}
return arr;
}
void sort(int arr[],int n)
{
int i,j;
int temp;
int flag;
for(i=0;i<n-1;i++)
{
flag=1;
for(j=0;j<n-i-1;j++)
{
if(arr[j]>arr[j+1])
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
flag=0;
}
}
}
return;
}
void print(int arr[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%d\t",arr[i]);
}
}
int main(void)
{
int i;
int*p;
p=creat();
sort(p,N);
printf("\n通过函数调用返回进行排序后的数组\n");
print(p,N);
free(p);
return 0;
}
运行结果:
creat()函数中产生数组元素
41 67 34 0 69 24 78 58
通过函数调用返回后得到的数组
41 67 34 0 69 24 78 58
采用这种方式同样可以得到正确的结果,只是,这个时候要注意在main()函数中采用free()函数进行内存释放时,不能使用arr作为参数,因为尽管为它申请的内存空间是从程序运行开始到程序运行结束,但是它并不是一个全局变量。在main()函数中使用指针p指向了内存单元的首地址,所以可以采用指针变量p作为free()函数的参数对申请的内存空间进行释放。