为什么我们需要在C中使用它们之前声明函数?

时间:2015-03-01 01:12:58

标签: c c99

在C99中,如果函数在声明之前被调用,编译器将发出警告。例如,这将导致警告:

int sum(const int k) {
  return accsum(k, 0);
}


int accsum(const int k, const int acc) {
  if (k == 0) {
    return acc;
  } else {
    return accsum(k-1, k + acc);
  }
}

int main() {
  int x = sum(3);
  return 0;
}

我在Googling之后看到的答案是需要声明,以便编译器可以检查参数类型以避免错误。但是为什么在从sum中调用accsum时,编译器才能在执行accsum之前找到accsum的函数定义?

2 个答案:

答案 0 :(得分:2)

这只是cicra 1970 C的剩余部分。

强制程序员在使用它们之前声明函数允许编译器一次通过(即只读取一次代码)。

40年前,限制编译时间非常重要。今天只是一个烦恼。

编辑:

当然,您必须声明 外部 函数原型,否则编译器无法知道哪些参数和返回值。这与声明的顺序无关。

安全和方便的做法是将未声明的外部函数视为错误,并从同一编译单元中的前向声明原型中分配程序员。

至于允许使用非原型功能,它是1970年左右的另一个剩余部分。 C99不再允许隐式声明,但您仍然可以使用K& R样式声明(没有参数参数规范的原型)。

我认为出于向上兼容的原因,这种危险的可能性得以保留。

答案 1 :(得分:2)

实际上,在C中使用之前不需要声明函数。如果遇到尝试调用函数,编译器将采用变量参数列表并且函数返回int。

现代编译器在查看声明之前尝试调用函数时发出警告的原因是声明允许编译器检查参数是否属于预期类型。给定声明,如果参数与函数声明中的规范不匹配,编译器可以发出警告或错误。这会让程序员发现很大比例的错误。

至于为什么编译器没有预见到定义,有一些因素。首先,有一个单独的C编译模型 - 不能保证在当前编译单元(即源文件)中找到一个函数定义。其次,它允许编译器在一次通过中工作,从而提高性能。第三,它确实鼓励程序员实际声明函数(例如在头文件中),这允许使用单独的编译模型重用。第四,它增加了编译器实际能够在内存资源有限的机器上运行的机会。