这条线的目的是什么? (function声明)

我正在通过K&R学习编程。 到目前为止还不错,但我不清楚第1.8节(函数)中的一行代码的作用。

在1.8节中,作者向您展示了如何创建一个函数来将一个整数提升到另一个整数的幂。

我已经粘贴了下面的代码,正如书中所写的那样。 一切都很好。 但我不知道为什么他们把这条线包括在最上面:

int power(int m, int n); 

这本书没有提到它,除了说该程序将整数m提高到幂n。 如果我从代码中删除该行,程序仍然按预期输出。

如果我理解这一点,就行了

 int power(int base, int n) 

创建函数,下面的大括号定义函数。 然后main下的大括号调用函数输出图表。

所以这一切似乎都有道理。 但我不明白最重要的是什么。

这可能是无关紧要的,但我似乎更有可能错过了一些东西。 任何人都可以告诉我为什么那条线在那里?

 #include  int power(int m, int n); /* test power function */ main() { int i; for (i = 0; i = 0 */ int power(int base, int n) { int i, p; p = 1; for (i = 1; i <= n; ++i) p = p * base; return p; } 

第一行是函数的声明 。 底部的代码块是函数的定义

从1999版ISO C标准开始,在没有可见声明的情况下调用函数是非法的(违反约束); 声明必须在通话之前。

对于像这样的简单程序,你可以在main()的定义之前编写power()的完整定义(因为定义也提供了声明),但是对于更复杂的情况(例如递归调用),你经常需要提供单独的声明。

对于较大的程序,通常会在头文件(例如foo.h )中收集所有函数声明 ,并在源文件(例如foo.c )中收集相应的定义。 #include "foo.h"指令用于使声明在其他文件中可见。 你会在书的后面看到那种事情。

(在1990年和早期版本的C中,这是K&R2所涵盖的,有些情况下你可以调用一个没有可见声明的函数 – 但是无论如何提供显式声明仍然是个好主意。)

顺便说一下,主程序的声明应该是int main(void)而不仅仅是main()

术语:“prototype”是一个函数声明,它指定参数的类型。

 int power(int base, int n); /* a declaration that's also a prototype */ int power(int, int); /* likewise */ int power(); /* a declaration but not a prototype */ 

(参数名称在定义中是必需的,但在独立声明中是可选的。)

作为一种特殊情况,没有参数的函数的原型使用(void) ,因为空括号已经意味着非原型声明。 所以int main(void)是原型,但int main()不是。

非原型声明是“过时的”,这意味着它们理论上可以从未来的语言标准中删除。 但它们自1989年以来已经过时,即使在新的2011 ISO C标准中,委员会也认为不适合将它们删除。

 int power(int m, int n); 

是原型forms的power函数声明。 函数声明通知编译器函数具有的参数个数,函数参数的类型以及函数返回值的类型。

在C中,在声明之前不能使用函数标识符。

它是一个前向声明 ,它使函数接口公开,因为函数在main()下实际实现之前使用。

头文件,你#include提供了类似的function,使可调用API公开 – 但代码通常在库中提供,而不是通过与K&R的单文件示例中的相同编译单元提供介绍章节。

如果您没有在顶部包含该行,则当程序达到power(2,i)尚未声明主电源。 程序从上到下读取,通过将声明放在顶部,编译器知道“定义即将来临”。

那条线只是函数原型。 它是一个前向声明 ,允许代码能够使用具有该签名的某些函数,当所有内容链接在一起时,该签名将存在。 没有它, main()函数将尝试使用power()函数,但编译器还没有意识到它,因为它实际上并未在源文件中实际定义。

您所指的顶部的那一行是函数原型。 它唯一的用途是编译器可以检查你的工作,也就是说,通过传递正确的类型和数量的参数来确保你正确使用该函数。 这就是它的全部。 这就是为什么你可以删除它并且代码仍然编译 – 你通过删除它所做的就是删除编译器的引用,这样它就无法检查你的工作。 如果你删除它,那么你可能会传递错误类型的参数并导致很难找到运行时错误或程序崩溃。 但保留它允许编译器在编译时标记这样的错误,从而节省一些悲伤。 拯救某人一些悲伤是件好事。

后来,根据C99标准,他们决定强制提供函数原型(或者首先定义函数)以便编译代码,从而迫使你让编译器检查你的工作。