Quantcast
Channel: Sam的技术Blog
Viewing all articles
Browse latest Browse all 158

C/C++参数

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

Sam第一语言是C语言,之后常使用C++. 但对函数参数的理解,还停留在C语言的概念里。今天,就把这块明确一下。


1:C语言参数
1.1: 形参和实参
形式参数(形参): 在函数定义中的参数,在整个函数体内都可以使用,离开该函则不能使用。
实际参数(实参): 出现在主调函数中,进入被调用函数后,实际参数也不能使用。

作用:
形参和实参的功能是做数据传递。
发生函数调用时,主调函数把实参的值传送给被调函数的形参,从而实现主调函数向被调函数的数据传送。这就是值传送

1.2:形参和实参的特点
A. 形参变量只有在函数被调用时才分配内存空间。 调用结束时,即刻释放所分配的内存。(所以形参只在函数内部有效)
B. 实参可以是常量, 变量,表达式,函数等。 但无论是何种类型,在进行函数调用时,他们都必须是确定的值。
C. 实参与形参在数量,类型,顺序上应该严格一致。
D. 函数调用中,数据传递是单向的,即实参把值copy给刚刚建立的形参,形参并不会把值传递给实参。所以改变形参的值,实参不变。

1.3:参数的传递过程
函数在被调用时,系统为形参分配一块内存空间,并把实参的内容copy给它。在函数体内,使用形参这个变量(内存)。 退出函数时, 临时存储区域被释放。
函数内部所用到的内存空间,由run-time stack配置而来,当函数结束时,这块内存空间会被立刻释放。

(与此类似,函数的返回值也是类似处理,返回值是局部变量,只在函数内有效,但在函数退出前,把返回值得内容copy给外部,所以局部变量销毁后,外部变量可以继续使用)

1.4:C语言中,数组作为参数
有些文档把数组名作为参数单列一种情况,其实它并不特殊。遵循的原则还是一致的---值传递。下面我们具体分析一下。
数组作为函数参数,又分两种情况:
1.4.1. 数组元素作为函数实参。与普通实参并无区别。都是值传递。


1.4.2. 数组名作为函数参数
数组名是个地址,即为数组的首地址。
数组名做参数,与数组元素做参数,在程序写法上有不同。
A. 使用数组元素做实参,只需要数组类型和函数形参类型一致即可。因此,并不需要函数形参也是下标变量。对数组元素的处理也是按普通变量对待。
而使用数组名作为实参时,则要求函数形参和相对应的实参都必须是类型相同的数组

B.在普通变量或者下标变量作为实参时,形参变量和实参变量是两个不同的内存区域。函数调用之初,,系统会把实参copy给形参。
在使用数组名作为实参时,数组名为指针, 它的值代表一个内存地址,形参的值就是一个内存地址。他们俩指向的同一块内存区域(数组)。 所以,他们的下标元素其实是同一套。

例1:
float average(float val[10]);





int main(int argc, char** argv)
{
float age = 0.0f; 

float fSize[10] = {1.2f, 3.4f, 1.0f, 3.4f, 6.5f, 7.2f, 3.5f, 4.0f, 4.4f, 6.6f};



printf("\nOld Data is: \n");
for(int i = 0; i < 10; i++)
{
printf("\t %f.\n", fSize[i]);
}

age = average(fSize);
printf("\nAverage is: %f\n", age);

printf("\nNew Data is: \n");
for(int i = 0; i < 10; i++)
{
printf("\t %f.\n", fSize[i]);
}

return 0;
}

float average(float val[10])
{
int index = 0;
float sum = 0.0f;

for(index = 0; index < 10; index++)
{
sum = sum + val[index];
}

for(index = 0; index < 10; index++)
{
val[index] = (float)index;
}
return sum/10;
}

这里有两点需要注意:
1. 在被调函数内,修改了数组参数的下标变量,结果实参也改变了。原因上面讲过。
2. 实参是数组名时,形参必须也是个同类型数组。
float average(float val[10]);

思考:
一个数组,如何定位,其实只需要一个数组名(头指针)和一个长度即可。
如例1 这样float average(float val[10]);
就固定了参数长度,如果未来要修改参数长度,就需要被调函数修改参数和内容。 所以其实可以不指定长度
如 float average(float val[], int len)
这样,如果实参所代表的数组长度改变,被调函数就不需要做任何修改了。(当然被调函数中10要转为len)





 

Viewing all articles
Browse latest Browse all 158

Trending Articles