题
要真正符合标准的,必须所有功能在C(除了主要)中有一个原型,即使他们仅使用后他们中的定义相同的翻译单位?
解决方案
这取决于你的意思是'真正的符合标准'.然而,简短的回答是"这是一个很好的想法,以确保所有功能原型的范围之前使用"。
一个更有资格回答指出,如果功能接受的变量的参数(值得注意的是的 printf()
家庭的功能),则一个原型必须在范围应严格符合标准。这是真正的C89(ANSI)和C90(从ISO;同C89除了部分的编号).比其他的'varargs'功能,虽然职能,其回报 int
不要宣布和功能返回的东西比一个 int
需要一个宣言,显示回返的类型,但不需要的原型参数清单。
然而,请注意,如果功能需要参数,受到正常的促销活动'在没有原型(例如,一个功能,需要一个 char
或 short
-两者都被转换成 int
;更严重的是,也许,一个功能,需要一个 float
而不是一个 double
),然后一个原型是必要的。该标准宽松的关于这个允许的老C码来编制在标准符合标准的编译器;旧编码未写的担心确保职能被宣布之前使用过的定义,老年码没有使用原型,因为他们没有成为提供C直到有一个标准。
C99不允许'隐含int'...这意味着这两个古怪的情况下,像'static a;
'(一个 int
通过默认)和也隐含的功能的声明。这些都是所提到的(与大约50个其他重大变化)在序言ISO/IEC9899:1999年
其中比较标准的先前版本:
- 消除隐性的
int
…- 消除隐性功能的声明
在ISO/IEC9899:1990年,§6.3.2.2 功能的电话 说明:
如果在表达之前的带括号的参数列在一个功能包括呼叫 仅仅一个标识符,并且如果没有《宣言》是可见的,对于这种标识,标识是隐含地 声明,正是因为如果在最里面包含块的功能的电话,声明:
extern int identifier();
出现。38
38 也就是说,标识与块范围的宣称有外部联系的类型功能没有 参数的信息和返回
int
.如果实际上这不是定义为具有类型的"功能 回int
"的行为是不确定的。
这一段缺失,在1999年的标准。我没有(尚未)行跟踪变化的措辞,允许 static a;
在C90和不允许它(要求 static int a;
)在C99。
请注意,如果一个功能是静态的,它可以限定在使用之前,并不需要之前,通过一项宣言。海湾合作委员会就可以说服惠如果一个非静态功能的定义没有《宣言》之前(-Wmissing-prototypes
).
其他提示
prototype 是一个函数声明,它指定函数参数的类型。
前ANSI C(1978年第一版Kernighan <!> amp; Ritchie's <!>所描述的语言; C编程语言<!>“)没有原型;函数声明不可能描述参数的数量或类型。由调用者传递正确数量和类型的参数。
ANSI C引入了<!> quot; prototypes <!> quot;,声明指定参数的类型(从早期的C ++中借用的一个特性)。
从C89 / C90(ANSI和ISO标准描述相同的语言)开始,调用没有可见声明的函数是合法的;提供了隐式声明。如果隐式声明与实际定义不兼容(例如,调用sqrt("foo")
,则行为是未定义的。此隐式声明和非原型声明都不能与可变参数函数兼容,因此对可变参数函数的任何调用(像printf
或scanf
一样,必须有一个可见的原型。
C99删除了隐式声明。对没有可见声明的函数的任何调用都是违反约束的,需要编译器诊断。但该声明仍然不需要成为原型;它可以是旧式声明,不指定参数类型。
C11在这方面没有发生重大变化。
因此,即使是2011 ISO C标准,仍然允许在符合规范的代码中使用旧式函数声明和定义(自1989年以来一直是<!>“obsolescent <!>”)。
对于可追溯到1989年的所有C版本,作为一种风格问题,没有理由不将原型用于所有功能。保留旧式声明和定义只是为了避免破坏旧代码。
不,功能并不总是需要原型。唯一的要求是函数是<!> quot;声明<!> quot;在你使用它之前。有两种方法可以声明一个函数:编写一个原型,或者编写一个函数本身(称为<!> quot; definition。<!> quot;)定义总是一个声明,但并非所有声明都是定义。
是的,每个函数都必须有一个原型,但该原型可能出现在单独的声明中,也可能出现在函数定义的一部分中。用C89编写的函数定义自然会有原型,但是如果你用经典的K <!> amp; R样式写东西,那么:
main (argc, argv)
int argc;
char **argv;
{
...
}
然后函数定义没有原型。如果你写ANSI C(C89)样式,那么:
main (int argc, char **argv) { ... }
然后函数定义有一个原型。
编写新函数时,一个很好的提示是将它们颠倒写入,并将main写在底部,这样当您改变主意关于函数的args或返回类型时,您也不必修复原型。不断修复原型,并在它们过时时处理所有编译器的警告变得非常乏味。
让函数顺利运行后,将代码移动到一个命名良好的模块,并将原型放在同名的.h文件中。它节省了大量时间。我在5年内发现的最大生产力援助。
据我所知(在ANSI C89 / ISO C90中),没有。我不确定C99;但是,我希望也一样。
个人注意事项我只在......时编写函数原型。
- 我需要(当A()调用B()和 B()调用A())或
- 我正在导出这个功能;否则,感觉多余。 醇>