数组名作函数参数
- 引例
- 思考
- 例2
- 通用性
- 指针形参和数组形参
- 几点说明
引例
在主函数
中输入10个整数,并存入一个一维数组中;然后在被调函数
中,将0号元素的值``改为原值的10倍;最后在主函数
中输出结果。
思路:
若想在被调函数中,对主调函数中某个局部变量的值进行修改,则必须将该局部变量的地址传递到被调函数中,然后以跨函数
间接引用的形式进行赋值。
代码实现
#include<stdio.h>
void fun (int *p);
int main(void)
{int a[10],i;for (i=0;i<10;i++)scanf("%d",&a[i]);fun(&a[0]);for (i=0;i<=9;i++)printf("%d",a[i]);return 0;
}
void fun(int *p)
{*p=*p*10;return 0;
}
执行过程分析
首先,程序的执行控制权在主函数,在主函数中,定义一维数组,整型变量i,然后完成对整型数组的赋值。当函数执行到:
fun(&a[0]);
此时,调用被调函数fun(),此时实参
是&a[0]
,传递给形参
,也就是在将a[0]的地址
传递给形参p
。
参数传递之后,程序的执行控制权交给了被调函数fun(),参数传递完成之后,就形成了如下这样的指向关系:
然后此时通过间接引用可以修改a[0]的值。
但是注意,不可以直接以以下这种方式直接引用
a[0]=a[0]*10;
因为a[0]是局部变量,只可以在主函数中使用。
之后,被调函数执行到return,返回到主调函数,此时函数的执行控制权交给了主函数。在主函数中,再完成一维数组元素的全部输出。
思考
那么,如果要在被调函数中对主调函数中的一维数组的所有元素
进行间接引用,是不是需要将每个
元素的地址都传递到被调函数中呢?
实际上,并不需要。这是因为数组中元素的地址是连续有序
的,只要知道数组中0号元素
的地址,就可以求得其他元素
的地址。
因此,只需要将数组的首地址
传递到被调函数中即可。`
例2
在主函数中,输入10个整数,并存入一个一维数组a中,然后在被调函数
中,将所有数组元素
的值修改
为原来的10倍;最后在主函数中输出结果。
思路:
1.在主函数中以数组名a
作为实参。
2.在被调函数中以指针变量p
作为形参。
3.那么,参数传递之后,在被调函数
中就可以用指针变量p来间接引用
主调函数中的数组元素了。
数组在内存中的地址是连续的,就可以知道其他元素的地址
我们知道a[0]的地址为p,依次我们可以知道a[1]的地址为p+1,a[2]的地址为p+2…a[i]的地址为p+i。
此时形成这样的指向关系:
代码实现
#include<stdio.h>
void fun (int *p);
int main(void)
{int a[10],i;for (i=0;i<10;i++)scanf("%d",&a[i]);fun(a);for (i=0;i<=9;i++)printf("%d ",a[i]);return 0;
}
void fun(int *p)
{int i;for (i=0;i<10;i++)*(p+i)=*(p+i)*10; //间接引用 *(p+i)即a[i]return ;
}
*(p+i)即a[i]的间接引用形式。
通用性
由于数组名
只是一个地址
,并未包含数组的长度信息,因此为了提高被调函数
的通用性
,通常需要设置另外一个参数,专门用来传递数组的长度
。
改进之后:
#include<stdio.h>
void fun (int *p,int n);
int main(void)
{int a[10],i;for (i=0;i<10;i++)scanf("%d",&a[i]);fun(a,10);for (i=0;i<=9;i++)printf("%d ",a[i]);return 0;
}
void fun(int *p,int n)
{int i;for (i=0;i<n;i++)*(p+i)=*(p+i)*10;return ;
}
原来的被调函数只能针对只有十个元素的数组进行修改,而上面修改过的被调函数可以针对具有n个元素的元素进行修改。因此,具有更好的通用性
。
可以发现,用数组名
作函数参数时,只需要向被调函数
传递数组的首地址
和长度
而不需要传递所有数组元素的值,因而具有较高的存储效率
和时间效率
。
指针形参和数组形参
尽管形参p
是指针变量
,而不是数组名,然后为了提高程序的直观性,C语言允许将间接引用
形式的*(p+i)
表示为数组元素形式的p[i]
。
从而可以将被调函数改写为下面的形式:
void fun(int *p,int n)
{int i;for (i=0;i<n;i++)p[i]=p[i]*10;return ;
}
甚至于函数头的指针形参,也可以改写成数组
形式,从而进一步将被调函数进一步改写为
void fun(int p[],int n) //*p改写为p[]
{int i;for (i=0;i<n;i++)p[i]=p[i]*10;return ;
}
从而改进之后完整的源程序:
#include<stdio.h>
void fun (int *p,int n);
int main(void)
{int a[10],i;for (i=0;i<10;i++)scanf("%d",&a[i]);fun(a,10);for (i=0;i<=9;i++)printf("%d ",a[i]);return 0;
}
void fun(int p[],int n)
{int i;for (i=0;i<n;i++)p[i]=p[i]*10;return ;
}
几点说明
1.将函数头中的指针
形参改写为数组
形式,只是为了直观。
从本质
上来说,数组形参
仍然是指针变量
,因此不必在当括号中指定数组形参的长度。
例如:
void fun(int p[],int n)
2.在被调函数函数头
中定义的数组可以称之为形参数组
。在本质上形参数组
与实参数组
是同一个
数组。
这是因为形参数组的元素p[i]
,等同于*(p+i)
,而 * (p+i)即p[i]
,又是实参数组元素a[i]
的间接引用形式
;从而p[i]
表示的数组元素就是a[i]
。