对C语言函数参数传递的探讨*
——以交换问题为例

2013-01-10 10:15宋美英
通化师范学院学报 2013年4期
关键词:主调指针C语言

宋美英

(吕梁学院 离石师范分校,山西 吕梁 033000)

C语言作为一种结构化程序设计语言,强调程序设计的风格,提倡程序结构的规范化,因此不可避免地需要使用函数调用,用函数作为构件,可以开发出结构清晰、功能齐全的大型程序.在C语言中,函数是程序的基本单位,一个C语言源程序可以由一个主函数或一个主函数和若干个其他函数组成,参数是实现函数间数据交换的主要通道.

1 形式参数和实际参数

在调用有参函数时,主调函数与被调函数之间有数据传递关系.定义函数时,出现在函数首部的参数称为“形式参数”(简称“形参”).主调函数中,调用函数时,函数名后面圆括号中所使用的参数称为“实际参数”(简称“实参”).实参与形参应保持个数一致、类型相同或兼容.

形参与实参占用不同的存储单元.作为局部变量,形参只在本函数体内有效.在未发生函数调用时,形参并不占用内存中的存储单元.只有在发生函数调用时,才为形参分配内存单元,同时将实参的值传递给被调函数的形参.在函数调用结束后,释放形参所占的内存单元.

2 函数参数的传递方式

在C语言中,参数间的数据传递是单向的,即数据只能由实参传给形参,而不能由形参传回给实参.根据参数类型的不同,可以将参数间的数据传递方式分为“值传递”和“地址传递”两种.下面通过几个交换问题的具体执行过程探讨C语言中函数参数的传递问题.

2.1 值传递

当参数为普通类型时,形参变量与实参变量占用不同的内存空间,形参的改变并不能影响所对应的实参的值.

[例1] void swap1(int x, int y)

{ int t;

t=x; x=y; y=t;

}

main( )

{ int a=5, b=9;

swap1(a,b);

printf(“a=%d,b=%d ”,a,b);

}

程序运行结果为:

a=5,b=9

由输出结果可以看出,实参变量a、b的值并没有发生交换.例1中各变量值的变化情况如图1所示.

图1 参数为普通类型时各变量变化情况

发生函数调用时,为形参x和y分配内存空间,同时实参把自己的值复制一份依次传递给形参,形参x和y分别得到5和9,然后形参使用得到的值参与被调函数中的运算.事实上,在值传递的过程中,有一项操作隐含在被调函数中.这个隐含操作确实存在,如果把它显式地写出来,可得被调函数如下:

void swap1(int x, int y)

{ int t;

x=a; y=b; //执行被调函数时的隐含操作

t=x; x=y; y=t;

}

现在问题变得清晰起来,发生函数调用时,只是隐含地把实参a、b的值通过赋值的方式传递给了形参x、y,形参并没有代替实参,修改形参也就并不意味着修改了实参.因此,在被调函数中交换了形参变量x和y的值,函数调用结束时,释放形参所占用的存储空间并返回主函数,此时形参x、y不复存在,而实参a和b的值并没有发生变化.

2.2 地址传递

当实参为变量的地址、指针变量或数组名等实质上表示地址的形式时,形参应使用指针变量或数组名.发生函数调用时,由形参接收实参中的地址值,此时,形参与实参指向同一段存储单元.如果在被调函数中修改形参指针所指向的地址中的内容,那么主调函数中变量的值也会发生同步改变.

[例2] void swap2(int *x, int *y)

{ int t;

t=*x; *x=*y; *y=t;

}

main( )

{ int a=5, b=9;

int *p1=&a, *p2=&b;

swap2(p1, p2);

printf(“a=%d, b=%d ”,a,b);

}

程序运行结果为:

a=9,b=5

由输出结果可以看出,主函数中的变量a、b的值发生了交换.例2中各变量值的变化情况如图2所示.

图2 参数为指针类型且交换指针所指内容时各变量变化情况

主函数中,实参指针变量p1和p2分别存放a、b的地址,发生函数调用时,传递的并不是变量的值,而是变量的地址,即将a、b的地址传给了形参指针x和y,这就是所谓的“地址传递”.其实它与值传递相同,同样在被调函数中有一项隐含操作如下:

void swap2(int *x, int *y)

{ int t;

x=&a; y=&b; //执行被调函数时的隐含操作

t=*x; *x=*y; *y=t;

}

由隐含的赋值操作可以看出,形参指针x和y分别存放a、b变量的地址值.接下来执行被调函数时,对*x和*y的操作也就是对a、b变量本身的操作.因此,交换了*x和*y的值,也就是交换了形参指针变量所指向地址中的内容.函数调用结束返回主函数时,释放形参所占的单元,不存在了的只是形参指针变量x和y,它们原来所指向单元中修改过的值被保留下来.本例主函数中的变量实现交换,这只是利用了指针对变量的间接访问方式,使用指针变量作参数,从而实现对主调函数中变量值的修改,这并不是由于数据从形参传回给了实参,实参向形参的单向数据传递性是不变的.因此,有的文献将地址传递描述为“双向传递”是不妥当的.

[例3] void swap3(int *x, int *y)

{ int *t;

t=x; x=y; y=t;

}

main( )

{ int a=5,b=9;

int *p1=&a,*p2=&b;

swap3(p1,p2);

printf(“a=%d,b=%d ”,a,b);

}

程序运行结果为:

a=5,b=9

由输出结果可知,使用指针变量作参数,也不一定能够改变主调函数中变量的值.这是因为虽然同例2相同,本例中的参数传递方式依然是地址传递,但函数swap3( )只是交换了x和y中所存放的地址,即改变了两个指针的指向,并没有改变指针所指单元中的值,因此主函数中两个变量的值并没有被交换.例3中各变量值的变化情况如图3所示.

图3 参数为指针类型且交换指针变量本身时各变量变化情况

3 结语

C语言中,一般将函数参数的传递方式分为值传递和地址传递两种,这只是根据参数类型的不同而进行的一种分类.值传递指参数为普通类型时的参数传递,而地址传递一般指参数的实质是地址类

的参数传递.事实上,无论参数的类型如何,参数间的数据传递方式都是单向的,即只能由实参传递给形参,值传递和地址传递的区别仅在于传递的数据类型不同.

参考文献:

[1]董汉丽.C语言程序设计[M].大连:大连理工大学出版社,2009.

[2]谭浩强.C程序设计(第四版)[M].北京:清化大学出版社,2010.

[3]董鑫正.C语言教学中函数参数传递问题的探讨[J].电脑知识与技术,2012(7).

[4]马新.C语言函数间参数传递机制的探讨[J].白城师范学院学报,2008(6).

猜你喜欢
主调指针C语言
化肥行业绿色低碳发展成主调
垂悬指针检测与防御方法*
基于Visual Studio Code的C语言程序设计实践教学探索
51单片机C语言入门方法
基于C语言的计算机软件编程
为什么表的指针都按照顺时针方向转动
高职高专院校C语言程序设计教学改革探索
浅析C语言指针
浅析图案的色彩与配色方法
用色彩点亮空间