13.2.2 函数的返回结果

和方法一样,函数也可以返回值。Return语句返回的值类型必须和函数声明的返回类型一致。如下函数


float kmh_to_mph(float km_speed)


定义了函数kmh_to_mph,它使用一个名为km_speed的float参数,并返回浮点型小数。类似地,


int gcd(int u, int v)


定义了一个名为gcd的函数,它传递整型参数u和v并返回一个整型值。

使用函数重新编写代码清单5-7中求最大公约数的算法。该函数的两个参数是想要计算最大公约数(gcd)的两个数(参见代码清单13-5)。

代码清单13-5


import<Foundation/Foundation.h>

//This function finds the greatest common divisor of two

//nonnegative integer values and returns the result

int gcd(int u, int v)

{

int temp;

while(v!=0)

{

temp=u%v;

u=v;

v=temp;

}

return u;

}

main()

{

NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];

int result;

result=gcd(150,35);

NSLog(@“The gcd of 150 and 35 is%i”,result);

result=gcd(1026,405);

NSLog(@“The gcd of 1026 and 405 is%i”,result);

NSLog(@“The gcd of 83 and 240 is%i”,gcd(83,240));

[pool drain];

return 0;

}


代码清单13-5输出


The gcd of 150 and 35 is 5

The gcd of 1026 and 405 is 27

The gcd of 83 and 240 is 1


函数gcd规定带有两个整型参数。该函数通过形参名称u和v来指明这些参数。将变量temp声明为整型之后,该程序将在终端显示参数u、v的值和相关消息。然后,这个函数计算并返回这两个整数的最大公约数。

表达式


result=gcd(150,35);


使用参数150和35来调用函数gcd,并且将返回值存储到变量result中。

倘若省略函数的返回类型声明,如果该函数确实返回任何值,编译器就会假设该值为整数。许多程序员利用这个事实,省略返回整数的函数返回类型声明。但是,这是不好的编程习惯,应该避免。

函数的默认返回类型与方法的默认返回类型不同。回想一下,如果没有为方法指定返回类型,编译器就假设它返回id类型的值。同样,应该总是声明方法的返回类型,而不是依赖于这个事实。

声明返回类型和参数类型

前面提到过Ojective-C语言编译器假设函数的默认返回值是整型值。更确切地说,无论什么时候调用一个函数,编译器都会假设这个函数的返回类型为int,除非发生以下两种情况之一:

·在遇到函数调用之前,已经在程序中定义了该函数。

·在遇到函数调用之前,已经声明了该函数的返回值类型。声明函数的返回值类型和参数类型称为原型(prototype)声明。

函数声明不仅用于声明函数的返回类型,而且用于告知编译器,该函数带有多少参数及其类型。这类似于定义新类时在@interface部分中声明方法。

要将absoluteValue定义为一个返回float型值并带有一个float类型参数的函数,可以使用以下原型声明:


float absoluteValue(float);


可以看到,只需要在圆括号中指定参数类型,而不是参数名称。如果愿意,可以选择在类型之后指定“伪”名称:


float absoluteValue(float x);


这个名称和函数定义所用到的不必相同,反正编译器会忽略它。

编写原型声明最简单的方法是简单地复制函数实际定义的第一行代码。记住在结尾处添加分号。

如果函数的参数数目不定(比如NSLog和scanf),必须告知编译器。如下声明


void NSLog(NSString*format,……);


告知编译器:NSLog将使用一个NSString对象作为它的第一个参数,之后是任意数目的附加参数(……的用途)。NSLog和scanf在一个特殊文件Foundation/Foundation.h[1]中声明,这就是为什么要在每个程序的开头添加下面一行语句。


import<Foundation/Foundation.h>


如果没有这一行语句,编译器可以假设NSLog使用固定数目的参数,这可以导致产生不正确的代码。

只有已经在调用函数之前添加了函数的定义或声明了该函数及其参数类型时,编译器才会在调用该函数时自动将参数转换成相应的类型。

下面是关于函数的一些注意事项和建议:

·默认情况下,编译器假设函数返回int。

·定义返回值为int的函数时,直接将它定义为int。

·当定义没有返回值的函数时,将它定义为void。

·只有当前面已经定义或声明了这个函数,编译器才会将参数转换成函数认可的类型。

为了安全起见,在程序中声明所有函数,即使它们在被调用之前已经定义了(将来你可能决定将这些函数移到文件的其他位置或者移到另一个文件中)。好的策略是将函数声明放到一个头文件中,然后只将这个头文件导入(import)你的模块即可。

默认情况下,函数是外部的。即,函数的默认作用域是任何与该函数链接在一起的文件中的任何函数或方法都可以调用它。通过将其定义为static(静态)可以限制函数的作用域。将关键字static放在函数声明前即可,如下所示:


static int gcd(int u, int v)

{

……

}


静态函数只可以由和该函数定义位于同一文件的其他函数或者方法调用。

[1]从技术上讲,是在文件NSObjCRuntime.h中定义,该文件是从文件Foundation.h内部导入的。