【问题标题】:What are the implications of having an "implicit declaration of function" warning in C?在 C 中出现“函数的隐式声明”警告意味着什么?
【发布时间】:2010-04-22 04:58:36
【问题描述】:

正如问题所述,“隐式声明函数”警告究竟意味着什么?我们刚刚在 gcc 上打开了警告标志,发现了很多这些警告的实例,我很好奇在修复它们之前这可能会导致什么类型的问题?

另外,为什么这是警告而不是错误。 gcc 甚至如何能够成功链接此可执行文件?正如您在下面的示例中所看到的,可执行文件按预期运行。

以以下两个文件为例:

file1.c

#include <stdio.h>

int main(void)
{
   funcA();
   return 0;
}

file2.c

#include <stdio.h>

void funcA(void)
{
   puts("hello world");
}

编译和输出

$ gcc -Wall -Wextra -c file1.c file2.c
file1.c: In function 'main':
file1.c:3: warning: implicit declaration of function 'funcA'

$ gcc -Wall -Wextra file1.o file2.o -o test.exe
$ ./test.exe
hello world

【问题讨论】:

    标签: c function prototype warnings declaration


    【解决方案1】:

    如果函数有一个与隐式声明相匹配的定义(即它返回int 并且有固定数量的参数,并且没有原型),并且你总是用正确的数量和类型来调用它论点,那么就没有负面影响(除了糟糕的、过时的风格)。

    即,在您上面的代码中,就好像函数被声明为:

    int funcA();
    

    由于这个与函数定义匹配,从file1.c 调用funcA() 会调用未定义的行为,这意味着它可能会崩溃。在您的架构上,使用您当前的编译器,显然不会 - 但架构和编译器会发生变化。

    GCC 能够链接它,因为表示函数入口点的符号在函数类型更改时不会更改(再次强调......在您当前的架构上,使用您当前的编译器 - 尽管这很常见)。

    正确声明你的函数是一件好事 - 如果没有其他原因,它允许你给你的函数一个原型,这意味着如果你用错误数量或类型的参数调用它,编译器必须诊断它.

    【讨论】:

    • 一点说明。当有疑问(即未定义)时,编译器假定函数的返回类型为 int 这是几个 C 编译器的默认行为。因此假设 int funcA( );
    • @caf:非常有趣。所以假设'funcA'有一个char* funcA(void);的原型,所以它返回了一个指向字符串的指针,我在strcpy中使用了返回值。使用隐式声明是否等同于执行strcpy(buff, (int)funcA())?我意识到未定义的行为就是这样,但我仍然很好奇我的实现实际上在做什么(Linux + gcc)。
    • @CVS:谢谢你的新词汇,我一定要记住那个!
    • SiegeX:这完全取决于您的架构 ABI,以及如何处理函数返回值。在 x86 上,指针和 int 返回值都在 %eax 寄存器中传递,因此它是等价的。请注意,在 x86_64 上,因为 char *int 的大小不同,它会截断指针值。
    • CVS:隐式声明的类型实际上是 C 语言规范的一部分,它不仅仅是某些编译器的默认值。
    【解决方案2】:

    它与使用具有int返回类型的非原型函数声明在块范围内具有相同的行为,因为无法指定返回类型它默认为int,就像 C 中所有未指定类型的声明一样,所有内容都是 int

    函数可以被隐式声明的原因是因为它们只能在文件范围内定义,但是不清楚未定义的变量是块范围还是文件范围,因此相反是不允许的选择一个并在文件或块范围内提供隐含的暂定定义。实际上,实际的隐含 声明 是块作用域的,因此在引用它的每个函数中第一次引用该函数时都会收到警告。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-13
      • 1970-01-01
      • 1970-01-01
      • 2013-11-27
      • 1970-01-01
      • 2022-01-14
      相关资源
      最近更新 更多