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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2575153/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:03:38  来源:igfitidea点击:

Must declare function prototype in C?

cfunctionfunction-prototypes

提问by Mohit Deshpande

I am kind of new to C (I have prior Java, C#, and some C++ experience). In C, is it necessary to declare a function prototype or can the code compile without it? Is it good programming practice to do so? Or does it just depend on the compiler? (I am running Ubuntu 9.10 and using the GNU C Compiler, or gcc, under the Code::Blocks IDE)

我对 C 有点陌生(我之前有 Java、C# 和一些 C++ 经验)。在 C 中,是否需要声明函数原型或者没有它可以编译代码?这样做是好的编程习惯吗?还是仅仅依赖于编译器?(我正在运行 Ubuntu 9.10 并在 Code::Blocks IDE 下使用 GNU C 编译器或 gcc)

回答by AnT

It is never required to declare a prototypefor a function in C, neither in "old" C (including C89/90) nor in new C (C99). However, there's a significant difference between C89/90 and C99 with regard to function declarations.

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

In C89/90 it was not necessary to declare a function at all. If the function is not declared at the point of the call, the compiler "guesses" (infers) the declaration implicitly from the types of the arguments passed in the call and assumes that the return type is int.

在 C89/90 中,根本不需要声明函数。如果在调用时未声明该函数,则编译器会根据调用中传递的参数类型隐式地“猜测”(推断)该声明,并假定返回类型为int.

For example

例如

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;
}

In C99 every function that you call must be declaredbefore point of the call. However, it is still not necessary to declare it with a prototypespecifically. A non-prototype declaration will work as well. This means that in C99 the "implicit int" rule no longer works (for inferred function return types, in this case), but parameter types can still be guessed from the argument types if function is declared without a prototype.

在 C99 中,您调用的每个函数都必须在调用点之前声明。但是,仍然没有必要专门用原型来声明它。非原型声明也将起作用。这意味着在 C99 中,“隐式int”规则不再有效(在这种情况下,对于推断的函数返回类型),但如果在没有原型的情况下声明函数,仍然可以从参数类型中猜测参数类型。

The previous example will not compile in C99, since foois not declared at the point of the call. Yet, you can add a non-prototype declaration

前面的示例不会在 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;
}
...

and end up with valid C99 code.

并以有效的 C99 代码结束。

Nevertheless, it is always a good practice to declare a prototype for the function before you call it.

尽管如此,在调用函数之前为其声明一个原型始终是一个好习惯。

An additional note:I said above that it is never required to declare a function prototype. In fact, for some functions it is a requirement. In order to properly call a variadicfunction in C (printffor example) the function must be declared with a prototypebefore the point of the call. Otherwise, the behavior is undefined. This applies to both C89/90 and C99.

附加说明:我在上面说过,永远不需要声明函数原型。事实上,对于某些功能,这是一项要求。为了在 C 中正确调用可变参数函数(printf例如),必须在调用点之前使用原型声明该函数。否则,行为是未定义的。这适用于 C89/90 和 C99。

回答by user308405

In ANSI C (meaning C89 or C90), you do not have to declare a function prototype; however, it is a best practice to use them. The only reason the standard allows you to not use them is for backward compatibility with very old code.

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

If you do not have a prototype, and you call a function, the compiler will infer a prototype from the parameters you pass to the function. If you declare the function later in the same compilation unit, you'll get a compile error if the function's signature is different from what the compiler guessed.

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

Worse, if the function is in another compilation unit, there's no way to get a compilation error, since without a a prototype there's no way to check. In that case, if the compiler gets it wrong, you could get undefined behavior if the function call pushes different types on the stack than the function expects.

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

Convention is to always declare a prototype in a header file that has the same name as the source file containing the function.

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

In C99 or C11, standard C requires a function declaration in scope before you call any function. Many compilers do not enforce this restriction in practice unless you force them to do so.

在 C99 或 C11 中,标准 C 要求在调用任何函数之前在范围内进行函数声明。许多编译器在实践中不会强制执行此限制,除非您强制它们这样做。

回答by Drakosha

it's not a must, if the function is defined before its use.

如果在使用之前定义了函数,则它不是必须的。

回答by R Samuel Klatchko

It is not required, but it is bad practice not to use prototypes.

这不是必需的,但不使用原型是不好的做法。

With prototypes, the compiler can verify you are calling the function correctly (using the right number and type of parameters).

使用原型,编译器可以验证您是否正确调用了函数(使用正确数量和类型的参数)。

Without prototypes, it's possible to have this:

没有原型,有可能是这样:

// file1.c
void doit(double d)
{
    ....
}

int sum(int a, int b, int c)
{
    return a + b + c;
}

and this:

和这个:

// file2.c

// In C, this is just a declaration and not a prototype
void doit();
int sum();

int main(int argc, char *argv[])
{
    char idea[] = "use prototypes!";

    // without the prototype, the compiler will pass a char *
    // to a function that expects a double
    doit(idea);

    // and here without a prototype the compiler allows you to
    // call a function that is expecting three argument with just
    // one argument (in the calling function, args b and c will be
    // random junk)
    return sum(argc);
}

回答by Raviteja

In C, if we do not declare a function prototype and use the function definition, there is no problem and the program compiles and generates the output if the return type of the function is "integer". In all other conditions the compiler error appears. The reason is, if we call a function and do not declare a function prototype then the compiler generates a prototype which returns an integer and it searches for the similar function definition. if the function prototype matches then it compiles successfully. If the return type is not integer then the function prototypes do not match and it generates an error. So it is better to declare function prototype in the header files.

在C中,如果我们不声明函数原型并使用函数定义,则没有问题,如果函数的返回类型为“整数”,程序将编译并生成输出。在所有其他情况下,都会出现编译器错误。原因是,如果我们调用一个函数而不声明函数原型,那么编译器会生成一个返回整数的原型,并搜索类似的函数定义。如果函数原型匹配,则编译成功。如果返回类型不是整数,则函数原型不匹配并生成错误。所以最好在头文件中声明函数原型。

回答by Anders Abel

C allows functions to be called even though they have not previously been declared, but I strongly recommend you to declare a prototype for all functions before using them so that the compiler can save you if you use the wrong arguments.

C 允许调用函数,即使它们以前没有被声明,但我强烈建议你在使用它们之前为所有函数声明一个原型,这样编译器可以在你使用错误的参数时拯救你。

回答by cpalmer

You should put function declarations in the header file (X.h) and the definition in the source file (X.c). Then other files can #include "X.h"and call the function.

您应该将函数声明放在头文件 (Xh) 中,并将定义放在源文件 (Xc) 中。然后其他文件可以#include "X.h"并调用该函数。

回答by zoli2k

Function prototype is not mandatory according to the C99standard.

根据C99标准,函数原型不是强制性的。

回答by Nikolai Fetissov

It's not absolutely necessary to declare a function for the calling code to compile. There are caveats though. Undeclared function is assumed to return intand compiler will issue warnings first about function being undeclared and then about any mismatches in return type and parameter types.

为要编译的调用代码声明一个函数并不是绝对必要的。不过也有一些注意事项。假定未声明的函数返回int,编译器将首先发出有关未声明函数的警告,然后发出有关返回类型和参数类型不匹配的警告。

Having said that it's obvious that declaring functions properly with prototypes is a much better practice.

话虽如此,很明显,使用原型正确声明函数是一种更好的做法。

回答by user3725015

Select ‘Options' menu and then select ‘Compiler | C++ Options'. In the dialog box that pops up, select ‘CPP always' in the ‘Use C++ Compiler' options. Again select ‘Options' menu and then select ‘Environment | Editor'. Make sure that the default extension is ‘C' rather than ‘CPP'.

选择“选项”菜单,然后选择“编译器 | C++ 选项'。在弹出的对话框中,在“Use C++ Compiler”选项中选择“CPP always”。再次选择“选项”菜单,然后选择“环境 | 编辑'。确保默认扩展名是“C”而不是“CPP”。