C89,C90或C99的所有function都需要原型吗?
为了达到真正的标准,C语言中的所有函数(main函数除外)都有一个原型,即使它们只在被定义在同一个翻译单元之后才被使用?
这取决于你的意思是“真正符合标准”。 但是,简短的回答是“确保所有function在使用前都有一个原型”是一个好主意。
更合适的答案指出,如果函数接受可变参数(特别是printf()
系列函数),那么原型必须严格符合标准。 C89(来自ANSI)和C90(来自ISO;与C89除了部分编号相同)都是如此。 不过除了'varargs'函数外,返回一个int
函数不一定要被声明,而返回int
以外的函数的函数也需要一个声明来显示返回types,但是不需要参数列表的原型。
但是请注意,如果函数在没有原型的情况下接受了“正常升级”的参数(例如,一个函数接受一个char
或者short
,两个都转换为int
;更严重的是,函数采用float
而不是double
),那么需要原型。 这个标准是松散的,允许旧的C代码在标准的符合性编译器下编译; 旧的代码没有写出来担心确保函数在使用之前被声明 – 根据定义,较旧的代码没有使用原型,因为直到有一个标准,它们在C中不可用。
C99不允许使用“implicit int”…这意味着两个古怪的案例,比如“ static a;
'(默认是一个int
)以及隐式函数声明。 在ISO / IEC 9899:1999的前言中提到了这些标准(以及其他约50个主要变更),该标准将该标准与以前的版本进行了比较:
- 删除隐式
int
…- 去除隐式函数声明
在ISO / IEC 9899:1990,§6.3.2.2 函数调用中声明:
如果函数调用中的括号括起来的参数列表之前的expression式仅由一个标识符组成,并且对于该标识符没有可见的声明,则该标识符被隐含地声明,就像在包含该函数调用的最内部的块中那样声明:
extern int identifier();
出现了。 38
38也就是说,一个块范围的标识符被声明为具有不带参数信息的types函数的外部链接并返回一个
int
。 如果实际上它没有被定义为具有types“返回int
函数”,则行为是未定义的。
1999年的标准中缺less这一段。 我还没有(跟踪)允许static a;
语言变化static a;
在C90中,并且在C99中禁止它(需要static int a;
)。
请注意,如果一个函数是静态的,那么它可以在使用之前被定义,并且不需要在声明之前。 GCC可以被劝说,如果一个非静态函数被定义而没有在它之前的声明( -Wmissing-prototypes
)。
不,function并不总是需要一个原型。 唯一的要求就是在使用它之前要先声明一个函数。 有两种方法来声明一个函数:编写一个原型,或者编写函数本身(称为“定义”)。定义总是一个声明,但并不是所有的声明都是定义。
原型是一个函数声明,用于指定函数参数的types。
Pre-ANSI C(Kernighan&Ritchie的“The C Programming Language”1978年第一版所描述的语言)没有原型; 函数声明不可能描述参数的数量或types。 这是由调用者传递正确的数量和types的参数。
ANSI C引入了“原型”,声明了指定参数types(从早期的C ++借用的一个特性)。
从C89 / C90开始(ANSI和ISO标准描述相同的语言),调用没有明显声明的函数是合法的。 提供了一个隐式声明。 如果隐式声明与实际定义不兼容(比如说调用sqrt("foo")
,那么这个行为是不确定的。这个隐式声明和非原型声明都不能和可变参数兼容,所以调用可变参数函数(如printf
或scanf
)必须具有可见的原型。
C99丢弃隐式声明。 任何不带可见声明的函数调用都会违反约束条件,需要编译器诊断。 但是这个声明还不是要成为一个原型; 它可以是不指定参数types的旧式声明。
C11在这一领域没有发生重大变化。
因此,即使在2011年的ISO C标准中,旧式函数声明和定义(自1989年以来已经“过时”)仍然被允许在符合的代码中。
对于所有C版本,回到1989年,作为一个风格问题,没有什么理由不使用原型来实现所有function。 保留旧式的声明和定义只是为了避免破坏旧的代码。
是的,每个函数都必须有一个原型,但是原型可能会出现在单独的声明中或作为函数定义的一部分。 用C89编写的函数定义自然就有了原型,但是如果你用经典的K&R风格写东西,那么:
main (argc, argv) int argc; char **argv; { ... }
那么函数定义就没有原型了。 如果你写ANSI C(C89)风格,那么:
main (int argc, char **argv) { ... }
那么函数定义就有一个原型。
据我所知(在ANSI C89 / ISO C90),没有。 我不确定C99; 然而,我期望相同。
个人笔记:我只写函数原型时…
- 我需要(当A()调用B() 和 B()时调用A())或
- 我正在导出函数; 否则,感觉是多余的。
编写新函数时的一个很好的提示是将它们与main的底部一起写下来,所以当你改变主意的时候,你不必修改原型。 不断修正原型,处理所有编译器的警告,当它们过时时,真的很乏味。
一旦你的function一起工作顺利,将代码移动到一个命名好的模块,并把原型放在一个同名的.h文件中。 这节省了很多时间。 我在5年中发现的最大的生产力援助。