【问题标题】:Implicit function declarations sometimes work in C?隐式函数声明有时在 C 中有效?
【发布时间】:2013-07-30 03:39:06
【问题描述】:

有人可以向我解释为什么以下编译:

int main()
{
    int a = mymethod(0);
}
int mymethod(int b)
{
    return b;
}

但事实并非如此:

int main()
{
    mymethod(0);
}
void mymethod(int b)
{
    return;
}

我认为 C/C++ 中需要前向声明,但这里有一个反例。隐式声明如何在 C 中工作?

【问题讨论】:

标签: c function forward-declaration implicit-declaration


【解决方案1】:

我假设当您说它在第二个代码示例中不起作用时,您的意思是您遇到了编译时错误。

原因是,当有隐式函数声明时,假定接受固定数量的参数,并返回int。但是,mymethod() 首先是隐式声明的,然后再声明返回 void。这是一个错误,因为新声明与之前的(隐式)声明不匹配。

C90 (ANSI C89) 允许隐式函数声明。来自 C89,第 3.3.2.2 节:

如果在括号内的参数列表之前的表达式 函数调用仅由标识符组成,如果没有 该标识符的声明是可见的,标识符是 隐式声明,就像在最里面的块包含 函数调用,声明

extern int identifier();
出现了。

但是,从 C99 开始,此允许已被删除(因此在 C11 中也不允许)。 C++ 从不允许隐式函数声明。

【讨论】:

  • 此外,在 C99 和 C11 中,对没有可见声明的函数的调用是违反约束。这意味着符合标准的编译器必须发出诊断,但不一定是致命错误。即使是符合 C99 的编译器也可以发出警告,然后使用 C90 语义。 (gcc -std=c99 -pedantic 执行此操作;如果您希望错误是致命的,则需要使用 -pedantic-errors。)
【解决方案2】:

编译器生成的隐式声明将假定函数的返回类型为int,这有时不是您想要的。避免使用它。

请注意,隐式声明仅在 C89 中有效,在 C99 中已被删除。 C++ 也不支持。

这可以在 C11(ISO/IEC 9899:201x) 标准中得到确认。

在 C11 Forward 部分,列出了第三版(即 C11)和第二版(即 C99)的所有主要变化,其中之一是:

第二版的主要变化包括:

...

——删除隐式函数声明

也在Rationale for International Standard Programming Languages C §6.5.2.2 函数调用中

C99 的一个新特性:在 C99 中删除了函数隐式声明的规则。其效果是保证生成将捕获额外类别的编程错误的诊断。发出诊断后,实现可以选择采用隐式声明并继续翻译,以支持利用此功能的现有程序。

【讨论】:

    【解决方案3】:

    默认假设是函数返回一个 int。所以第一个工作(幸运的是)因为情况就是这样。一般不会。

    【讨论】:

      【解决方案4】:

      对于 C99 中的隐式函数,该函数必须在被调用之前声明。在声明编写正确的函数原型时。默认方法声明原型具有返回类型“int”,这就是为什么它可以正常工作(在您的示例的第一种情况下)并带有一个警告(例如“函数的隐式声明在 c99 中无效”)。 但是在第二种情况下,您更改了默认原型,因此您需要声明其原型。

      例如:

      //Function prototype declaration
        void mymethod(int);  
      
      //Implementations
        int main()
        {
          mymethod(0);
        }
      
        void mymethod(int b)
        {
           return;
        }
      

      【讨论】:

        猜你喜欢
        • 2012-02-29
        • 2016-08-10
        • 2017-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多