执行该程序输出如下结果: 10,15,25 5,15 ,25 说明:
(1)该程序由主函数main ( )和被调用函数fl()组成,fl ()函数无返回值,由于定义fl()时没有加任何类型说明符,尽管调用在先定义在后也不必说明。
(2)在调用函数fl()时,3个实参中,一个是用变量名,另外2个用变量的地址值;在对应的形参中,一个是用变量名,另外2个用指针。在调用fl()函数中,有一个参数属于传值调用,2个参数属于传址调用。在被调用函数f1()中,改变了变量x的值,由于传值调用对调用函数对应实参a的值并没有被改变,这是传值调用的特点。同时,通过用运算符,对指针y和:取其内容,并且通过赋值表达式语句来改变了x和Y的内容,于是调用函数中对应的实参b和c的值被相应改变,这便是传址调用的特点。
该例程序中值得注意的是要在传址调用中通过被调用函数来改变调用函数的参数值时,一定要改变形参指针所指向的内容,而不能只改变形参的地址值,改变形参地址值是不会影响对应实参的变量值的。下面的例子将说明这一点。
[例5.5] 分析下列程序的输出结果。 main ( ) {
int a,b,c,d; a=b==c=d=5; f1(&a,&b); f2(&c,&d),
printf(\) } fl(x,y) int *x,*Y} { *x*=2; y+=*x;
printf(\); } f2(m,n) int *p,*q; p=q=8; p=q=8; m=&p n=&q
;
printf(\); }
执行该程序输出结果如下: 10,15 8, 8 to,15,5 ,5 说明:
(1)该程序由三个函数组成,除了主函数main()外,还有二个被调用用函数fl()和f2()。这两个被调用函数都是没有返回值的。在main ( )函数中,先调用f1()函数,再调用f2()函数。
(2)在调用fl()函数时采用了传址调用方式,即实参用变量a和b的地址值&a和&b,形参用指针x和Y.在fl()函数中,通过使用取内容运算符改变了指针x和Y所指向的变量的值(即改变了指针所指向的内容).因此,fl()函数被调用后,土函数中变量a和b的值发生了变化,这是通过传址调用改变调用函数参数值的又一个例子。
(3)在调用f2()函数时也采用了传址调用方式,即实参用变量。和d的地址值&c和&d,形参用指针m和n.在f2()函数中,形参m和n的地址值发生了变化,使m和n指向了变量P和q,于是m
和n所指向的内容将是P和9变量的值8.这时,如果要再改变m和n所指向的内容,只是改变变量P和q的值,也不会影响调用函数的参数值。因此,简单地说\传址调用中通过改变形参的值来改变调用函数中参数的值\这句话是不确切的。一定要指出在被调用函数中通过改变形参所指的内容才能改变调用函数中实参的值。
5.3.3 数组名作参数的函数调用
数组元素可作为实参,实现传值调用,这与变量名作实参一样,都是单向传递的。
数组名作函数实参与数组元素作实参是不同的,因为C语言规定数组名是一个地址值,即是该数组首元素的地址值。因此,数组名作实参时,要求形参也是数组名或者指向数组的指针,关于指向数组的指针将在下一章\指针\中讲解,这时实现的不是传值调用,而是传址调用。调用函数不是将整个数组的所有元素拷贝成副本传递给被调用函数,而是只将其数组的首元素地址值传给形参数组,于是这两个数组将共同占用同一段内存单元,这就是让形参数组的首元素地址与实参的首元素地址相同,使得这两个数组的对应元素同占一个内存单元。因此要求这两个数组要类型相同,数组的大小可以一致,也可以不一致。如果要使形参数组得到实参数组的全部元素,则形参数组与实参数组应大小一致。
下面举例说明用数组名作函数参数的调用方法。
[例5. 6] 编程对某一数组中的各个int型数进行由小到大的排序。
本例中采用算法简单的选择排序法。程序内容如下: main () {
void sort();
static int a[8]={5,一2 .9,87,0,6,21.49:}; Int i n: Sort(a.n);
for(i=O;i<8;i十十)
printf (\printf (\}
void sort(b,m) int b[],m; {
int i,j,k,temp; for(i=O;i for(j=i+1;j