编译器不喜欢惊喜
当编译器看到这行代码时会发生什么?
printf("Total so far: %.2f\n", add_with_tax(val));
- 编译器看到了一个不认识的函数调用。
编译器没有报错,而是认为它会在之后的源文件中找到这个函数的详细信息。编译器先记下,随后会在文件中查找函数,很不幸,问题就出在这个地方……
- 编译器需要知道函数的返回类型。
当然了,编译器现在还不知道函数的返回类型,所以只好假设它返回int
。
- 等编译器看到实际的函数,返回了“conflicting types for 'add_with_tax'”错误。
因为编译器认为有两个同名的函数,一个是文件中的函数,一个是编译器假设返回int
的那个。
脑力风暴
计算机假设函数返回
int
,但实际返回了float
。如果让你设计C语言,你会怎么解决这个问题?
你只要把函数放回正确的位置,在main()调用它之前先定义。
改变函数的顺序,编译器就不用假设未知函数的返回类型,因为这样的假设通常很危险。但如果总是以特定的顺序定义函数,会带来很多后遗症。
调整函数的顺序很痛苦
假设你在代码中添加一个新函数,人人都赞不绝口:
int do_whatever(){...}
float do_something_fantastic(int awesome_level) {...}
int do_stuff() {
do_something_fantastic(11);
}
为了完善程序,你决定在do_whatever()
函数中调用do_something_fantastic()
,为此必须将do_something_fantastic()
函数提前。程序员希望不断改进程序的功能,因此最好有一个两全其美的方法,既不用交换代码的顺序,又能让编译器高兴。
在某些场景中,没有正确的顺序
这种场景有些罕见,但有时你也许想写一些相互递归调用的代码:
如果有两个函数,它们互相调用对方,那么总有一个函数在定义前被调用。
出于以上两个原因,你希望更自由地定义函数,那么该怎么做呢?