【问题标题】:A function's prototype is similar to declaring the function in the calling routine?函数的原型类似于在调用例程中声明函数?
【发布时间】:2020-02-28 10:04:14
【问题描述】:

如果没有函数原型,则函数在其首次出现在表达式中时被隐式声明。

在 C 语言中,如果函数返回 int 以外的任何内容,最好在调用者函数中声明函数,如第一个代码示例

但是你总是受制于编译器编写原型,原因是他不知道函数是谁,因为它是在main()函数下面声明的。

问题是:这两者是等价的吗?是否编写原型或显式声明 main() 中的函数会返回 wanted 结果?如果您总是约束使用这两种方式之一,它怎么会返回一个错误的值?

  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

【问题讨论】:

    标签: c function scope declaration


    【解决方案1】:

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

    在这段代码中sn-p

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

    有函数doSomething的函数原型。

    来自 C 标准

    函数原型是一个函数的声明,它声明了 参数类型

    也就是说,在函数定义之前也是它的声明,函数的名称将仅在 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 块范围内的名称已经声明。

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

    所以 main 中的这个声明

        double doSomething(int a);
    

    等价于声明

        extern double doSomething(int a);
    

    即使函数最初是在块作用域中声明的,链接器也会找到函数定义。

    【讨论】:

    • 所以即使在主函数内部也可以编写原型?不是必须在外面吗?
    • 这是否意味着doSomething 原型仅在main 中可见(已知)并且在其定义(即函数实现)之前对其(main 之外)的任何使用都会导致错误?
    • @CătălinaSîrbu 正如我所写,如果一个函数在 main 函数之外不需要,那么它的原型可以放在 main 的范围内。
    • 你怎么能得到一个不需要的return类型?我的意思是如果函数的返回类型是double,你能给我一个例子,由于缺少声明,它如何转换为int(默认值)?假设程序不应该给出任何错误
    • @PaulOgilvie 是的,名称不会在函数定义之前在其他范围内声明。
    【解决方案2】:

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

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

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

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

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

    【讨论】:

    • 我认为你不能在另一个函数中声明一个函数。这是 C 所禁止的(在您的 在另一个函数中声明一个函数并没有明显错误
    • @CătălinaSîrbu:当然你可以在另一个函数中声明一个函数。 int main(void) { int square(int); } 严格符合 C。您不能在严格符合 C 的情况下在另一个函数中定义一个函数,尽管符合 C 并不禁止; C 实现可能允许它。
    • 哦!我混淆了这些术语
    猜你喜欢
    • 2011-08-07
    • 2012-07-15
    • 2021-03-17
    • 2016-05-23
    • 2018-03-14
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    相关资源
    最近更新 更多