为了账号安全,请及时绑定邮箱和手机立即绑定

必须在C中声明函数原型吗?

必须在C中声明函数原型吗?

C
波斯汪 2019-07-09 12:47:37
必须在C中声明函数原型吗?我对C有点陌生(我有以前的Java、C#和一些C+经验)。在C中,是否有必要声明一个函数原型,或者代码可以在没有它的情况下编译?这样做是好的编程实践吗?还是仅仅依赖于编译器?(我正在运行Ubuntu9.10,并在代码:块IDE下使用GNU C编译器或GCC)
查看完整描述

3 回答

?
慕沐林林

TA贡献2016条经验 获得超9个赞

在ANSI C(意思是C89或C90)中,您不必声明函数原型;然而,使用它们是最佳实践。该标准允许您不使用它们的唯一原因是为了与非常旧的代码向后兼容。

如果您没有一个原型,并且调用了一个函数,编译器将从传递给该函数的参数中推断出一个原型。如果稍后在同一个编译单元中声明函数,则如果函数的签名与编译器猜测的不同,则会出现编译错误。

更糟糕的是,如果函数位于另一个编译单元中,则无法获得编译错误,因为没有原型就无法检查。在这种情况下,如果编译器弄错了,如果函数调用在堆栈上推送的类型与函数所期望的不同,您可能会得到未定义的行为。

约定是始终在与包含函数的源文件同名的头文件中声明原型。

在C99或C11中,标准C在调用任何函数之前需要在作用域中声明函数。许多编译器实际上并不强制执行此限制,除非您强迫他们这样做。


查看完整回答
反对 回复 2019-07-09
?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

从来不需要声明原型对于C中的函数,无论是在“旧”C(包括C89/90)中还是在新C(C99)中。但是,在函数声明方面,C89/90和C99之间有显著差异。

在C 89/90中,根本没有必要声明一个函数。如果函数未在调用点声明,编译器“猜测”(推断)将从调用中传递的参数类型隐式地推断声明,并假定返回类型为int.

例如

int main() {
  int i = foo(5); 
  /* No declaration for `foo`, no prototype for `foo`.
     Will work in C89/90. Assumes `int foo(int)` */

  return 0;}int foo(int i) {
  return i;}

在C99中,您调用的每个函数都必须是申报打电话之前。但是,仍然没有必要使用原型特别是。一个非原型声明也将工作。这意味着在C99中“隐式”int“规则不再起作用(在本例中,对于推断的函数返回类型),但是参数类型仍然可以从参数类型中猜测,如果函数是在没有原型的情况下声明的。

前面的示例不会在C99中编译,因为foo没有在调用点声明。但是,您可以添加一个非原型声明。

int foo(); /* Declares `foo`, but still no prototype */int main() {
  int i = foo(5); 
  /* No prototype for `foo`, although return type is known. 
     Will work in C99. Assumes `int foo(int)` */

  return 0;}...

最后得到有效的C99代码。

尽管如此,在调用函数之前声明一个原型始终是一个很好的实践。

另一份说明:我前面说过,它从来不需要声明一个函数原型。事实上,对于某些功能来说,这是一个要求。为了正确地调用千变万化C中的函数(printf例如,必须声明函数带着一个原型在打电话之前。否则,行为是未定义的。这既适用于C89/90也适用于C99。


查看完整回答
反对 回复 2019-07-09
  • 3 回答
  • 0 关注
  • 1299 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信