【问题标题】:implicit declaration warning: What are the built-in functions?隐式声明警告:内置函数是什么?
【发布时间】:2013-11-27 23:17:48
【问题描述】:

提问界面标记了许多“可能已经有你答案的问题”,但我已尝试尽职调查以检查是否有任何人在问我在这里的确切内容。如果这是重复的,我深表歉意。

假设我有以下不正确的程序:

外部无效未定义函数(无效); int main(int argc, char **argv) { 未定义函数(); undeclared_function(); 退出(0); }

用 gcc 编译得到:

$ gcc 警告.c warnings.c:在函数“main”中: warnings.c:6:2: 警告:内置函数‘exit’的隐式声明不兼容 [默认启用] /tmp/ccVzjkvX.o:在函数“主”中: warnings.c:(.text+0x15): undefined reference to `undefined_function' warnings.c:(.text+0x1f): undefined reference to `undeclared_function' collect2: ld 返回 1 个退出状态 $

我知道为什么会发出这些警告,以及如何纠正它们 - 这不是我的问题。

从输出中可以看出,gcc 将exit() 与其他未定义/未声明的函数区别对待,因为它认为它是“内置函数”

对于给定的 gcc,我如何知道 gcc 认为是“内置函数”的函数列表是什么? 究竟是c标准库函数列表还是其他?

我考虑过nm libc.so,但是在我的 Ubuntu VM 上,这个 glibc 似乎被剥离了,所以在这方面没有有用的信息:

$ nm /lib/x86_64-linux-gnu/libc.so.6 nm:/lib/x86_64-linux-gnu/libc.so.6:无符号 $

【问题讨论】:

    标签: c gcc standard-library gcc-warning


    【解决方案1】:

    这个列表很长,而且是针对特定平台的。 C 标准库中的许多(但绝不是全部)函数(有时)被视为内置函数。但也有大量与特定处理器指令和其他硬件特性相关的内置函数。它们记录在与here; 链接的各个页面中,特别是,请参阅here,here,here,herehere.

    【讨论】:

    【解决方案2】:

    在深入研究 gcc 文档之后,我想我找到了一个合理的部分答案 (though this answer is more complete in its references):

    http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Other-Builtins.html#Other-Builtins

    “GCC 包含标准 C 库中许多函数的内置版本”(强调我的)。我认为这意味着大多数但不是所有标准库函数都是内置的。

    文档继续列出了适用于各个级别的 c 标准的几个列表:

    “ISO C90 函数 abort, abs, acos, asin, atan2, atan, calloc, ceil, cosh, @9876 , exit, ..."


    不是 gcc 内置的标准库函数的示例是bsearch()。如果我在程序中添加对此的调用,不使用#include <stdlib.h> 并使用-Wimplicit-function-declaration 进行编译,我会得到:

    warnings.c:5:2: warning: implicit declaration of function ‘bsearch’ [-Wimplicit-function-declaration]
    

    而对于exit(),我得到:

    warnings.c:8:2: warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration]
    warnings.c:8:2: warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default]
    

    【讨论】:

      【解决方案3】:

      您正在编译允许隐式声明的 C,因此您的“退出”是隐式声明的。并且编译器相信您稍后会定义它。

      隐式声明很好,如果您以通常的行为隐含退出(隐含的原型与实际原型相同)就可以了。

      GCC 只能告诉您有关内置的​​,因为您知道对于 C 编译器,stdlib 将在那里。这些是它知道存在(内置)的唯一功能,可以告诉您您的暗示是错误的

      否则我可以在我的桌面上有一个定义原型的头文件,并且当在其他地方编译某些东西时会得到一个关于它的警告。 GCC 将不得不扫描任何地方,这是不可取的.... 等等,如果您隐式定义某些内容并且稍后在翻译单元或实际版本(或另一个隐式)不同意,您只会收到这样的隐式警告。

      GCC 知道 stdlib = 内置。

      附录

      GCC 相信你的话,未定义的函数将存在,使用隐含声明的东西,没有什么与它相矛盾的,所以没关系。它不知道undeclared_function 应该是什么样子,但它知道exit 应该是什么样子。

      然后如您所知,链接器会抛出一个合适的结果(当然是正确的),因为它找不到它们。

      【讨论】:

      • 这很有用,但我特别要查找的是函数的确切列表,无论是一些 gcc 或其他工具输出,还是文档
      • @DigitalTrauma 整个 C 标准库。只需包含每个 heaver 文件,并让 GCC 输出一个声明列表。您可以使用一些标志进行编译,告诉它不要使用标准库(例如,如果您正在制作内核......)顺便说一句。
      • 投反对票不是我的。但是我刚刚找到的答案和你的不太一样。
      • "你正在编译允许隐式声明的 C" -- 不太正确。 C90 允许隐式声明(并假定被调用函数返回 int),但 C99 不允许。从 C99 开始,调用没有可见声明的函数是违反约束,需要进行诊断。默认情况下,gcc 使用 GNU 特定的扩展编译 C90。你可以使用-std=... 来改变它。
      • @AlecTeal:如果您回复某人,请在此人的姓名前加上一个 at 符号;否则不会通知他们您的回复。我只是偶然看到你的评论。不,我们并不是“全部”假设 C 表示带有 GNU 扩展的 C90。 C的当前官方版本是由2011 ISO标准定义的。隐式函数声明于 1999 年从该语言中删除,并且一直都是一个坏主意。这不是迂腐,而是准确。
      猜你喜欢
      • 1970-01-01
      • 2012-06-15
      • 2012-01-16
      • 2010-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多