术语:前向声明与函数原型

Posted

技术标签:

【中文标题】术语:前向声明与函数原型【英文标题】:Terminology: Forward Declaration versus Function Prototype 【发布时间】:2012-01-19 17:50:56 【问题描述】:

对我来说,这些术语在使用 C 编程语言时基本上是同义词。在实践中,我可能更喜欢文件内原型的“前向声明”,而不是通过头文件包含的原型的“函数原型”。但是,当您考虑预处理后会发生什么时,即使这是人为的区别。也许我错过了什么。

对于何时使用一个术语与另一个术语是否达成共识?

【问题讨论】:

【参考方案1】:

术语“原型”是指特定的声明语法;具体来说,函数参数的数量和类型出现在声明中。给定一个函数定义

int foo(int a, char *b) ...

您可以拥有以下任何声明

int foo();                // a declaration, but not a prototype
int foo(a, b);            // a declaration, but not a prototype
int foo(int, char *);     // a declaration and a prototype
int foo(int a, char *b);  // a declaration and a prototype

【讨论】:

您的选项 int foo(a, b); 仅在 ab 是已知类型名称时有效,或者如果它后跟函数体 而不是分号。【参考方案2】:

我不知道是否有共识,但我认为最干净的方法是:

将所有声明放在头文件中,切勿放在源文件或 .c 文件中。 (我认为当您说前向声明时,您的意思是声明。) 将所有定义放在源文件中

我不喜欢将声明放在文件中,因为在 C 中可以有冲突的声明而不会出现错误,这可能会导致段错误,例如:如果 a.c 有

int foo(char *str_one, char *str_two, char *str_three);

b.c 有

int foo(char *str_one, char *str_two);

您不会收到警告或错误,并且从 bc 对 foo() 的调用不会将所有参数放在堆栈中应有的位置,这意味着 foo() 只会从堆栈中抓取一些东西并将其视为 str_three ,可能导致段错误。所以对我来说,声明放在头文件中,定义放在源文件中。

【讨论】:

static 函数的声明应该放在他们在 imho 中定义的 C 文件中,最好放在开头。 @tristopia - 好点,当我在那里使用我的肥皂盒时,我并没有考虑静态函数。我绝对不会在头文件中声明它们。【参考方案3】:

IMO 这些并不是真正的同义词。 对我来说,“函数原型”是指函数名及其参数和返回类型。它不仅适用于您所说的“前向声明”。所有函数都有一个原型。

我们经常在函数声明与其对应的定义之间做出区分。

【讨论】:

+1,尽管使用“原型”这个词来指代声明确实很常见。 我想你和@MatteoItalia 已经总结了。当我应该使用术语声明时,我一直在使用术语原型。【参考方案4】:

我使用术语前向声明来表示以下带有定义的struct 声明。

struct Foo;

为了与 1989 年之前的 (K&R) C 兼容,函数声明不必是完整的原型。

char *foo();  // NOT the same as char *foo(void)

【讨论】:

【参考方案5】:

我知道的 C 语言中唯一的概念是声明和定义之间的区别。原型是一种声明,可以随时随地发生,并且定义是给定对象的实际实现。按照这个概念,没有什么叫做前向声明,只有一个声明的顺序。

【讨论】:

以上是关于术语:前向声明与函数原型的主要内容,如果未能解决你的问题,请参考以下文章

在构造函数与原型中声明javascript对象方法[重复]

c++原型与ANSI原型

我要查一些API函数的原型,在哪里查呢?

原型链步骤分解

函数原型函数声明和函数定义之间关系

第5章 数据的共享与保护