函数的原型类似于在调用例程中声明函数?

A function's prototype is similar to declaring the function in the calling routine?

If there is no function prototype, a function is implicitly declared by its first appearance in an expression.

在 C 中,如果一个函数 return 除了 int 以外的任何东西,在调用函数中声明函数是一个好习惯,例如 第一个代码示例 .

但是你总是被编译器逼着写原型,原因是他不知道这个函数是谁,因为它是在main()函数下面声明的。

问题是:这两个是等价的吗?将编写原型或在 main() return 中显式声明函数 wanted 结果?如果您 受限 总是使用这两种方式中的一种,它怎么会 return 是一个错误的值?

  1. 如果函数是在与调用函数相同的脚本中声明的(此处 main()
    • 原型
    • main() 中显式声明函数。
  2. 如果函数在另一个文件中声明
    • 原型
    • main()
    • 中显式声明函数

例如:

int main()
{
    double doSomething(int a);
    printf("%d", doSomething(2) );
}
double doSomething(int a)
{
     return a * 2.0;
}

double doSomething(int a);

int main()
{
    printf("%d", doSomething(2) );
}
double doSomething(int a)
{
     return a * 2.0;
}

这个帖子几乎是我所需要的,但它没有回答我所有的问题。 C language - calling functions without function prototype

这两个声明是等价的,直到在第一种情况下函数 doSomething 将在除 main 之外的其他函数中需要。

在此代码段中

int main()
{
    double doSomething(int a);
    //..

有一个函数原型doSomething

来自 C 标准

A function prototype is a declaration of a function that declares the types of its parameters

在函数定义(也是它的声明)之前,函数的名称将仅在 main 的块范围内可见。

考虑以下程序

#include <stdio.h>

void g( void )
{
    f( 20 );
}

int main(void) 
{
    void f( int );

    f( 10 );

    return 0;
}

void f( int x )
{
    printf( "x = %d\n", x );
}

编译器将针对此语句发出错误

    f( 20 );

因为名字f还没有声明。

但是这个说法

    f( 10 );

是正确的,因为 main 的块范围内的名称已经声明。

为了更清楚地考虑,函数始终具有与在没有存储 class 说明符的块作用域中声明的变量相反的链接。

所以这个在 main

中的声明
    double doSomething(int a);

相当于声明

    extern double doSomething(int a);

即使函数最初是在块范围内声明的,链接器也会找到函数定义。

在现代 C 语言中,您应该始终在使用函数之前对其进行声明。 (这包括在使用它之前定义一个函数,因为定义是一个声明。)return int 的函数隐式声明是非常旧版本的 C 的行为。它不应该被使用,编译器至少应该对此发出警告,并且您应该将编译器设置为错误,而不是警告。

函数通常在其他函数之外声明。在另一个函数中声明一个函数并没有明显的错误,但我们很少这样做,因为我们通常希望函数在整个翻译单元中都是可见的,而不仅仅是在一个特定的地方。 (翻译单元是一个源文件以及它通过 #include 指令包含的所有文件。)函数的名称遵循与对象名称相同的 scope 规则:如果它出现在任何函数之外,它具有 文件范围 。如果它出现在 内(大括号内的语句列表,{ … },其中包括函数体),它具有 块作用域 并且仅在该块中可见。

函数是在文件作用域还是块作用域声明都不会影响它的行为方式。

main在这方面并不特殊。您可能会询问 main,因为您处于编程教育的早期阶段,而且您大多只从 main 调用函数。但是,可以从其他函数调用函数,并且关于范围和名称可见性的规则并不是 main 所特有的。如果一个函数是在文件范围内声明的,那么它的名字在整个翻译单元的其余部分都是可见的。如果函数是在块范围内声明的,无论是在 main 还是在另一个函数内,它的名称在该块的其余部分都是可见的。

如果一个函数被定义为 return double 但您在未声明的情况下使用它,并且您的编译器允许这样做,那么您的程序可能无法正确运行。编译器不会自动将 double 转换为 int。函数类型对于告诉编译器函数 returns 是什么很重要,因为编译器期望某些位在函数 returns 时位于某些位置,并且它会根据此编写指令。