【问题标题】:Why don't I have "undefined reference to"? [duplicate]为什么我没有“未定义的引用”? [复制]
【发布时间】:2016-09-05 13:38:45
【问题描述】:

我在我的(大)项目中遇到了similar problem

//# include <string.h> // not included

void foo(char * str, const char * delim)
{
    char * tok = strtok(str, delim); 
    // warning ^ "assignement makes pointer from integer without a cast"

    // [...]
}

答案(只需添加#include &lt;string.h&gt; 以获得strtok 的原型)确实解决了问题。

但是,由于我对编译器/链接器的了解不足,我无法理解进程如何接受尚未原型化的函数。 我宁愿期待错误 undefined reference to function 'strtok' 当您忘记包含正确的标题时这是典型的。

[编辑] 我理解为什么这个问题被标记为重复,但我认为它是不同的:我知道关于包含的“良好做法”,我只是想知道编译器的行为。但是我承认我可以在这篇文章中找到(部分)我的问题的答案:Are prototypes required for all functions in C89, C90 or C99? 或这个:Must declare function prototype in C?

【问题讨论】:

  • 简短回答:如果将代码编译为 C99 或更高版本,则会出现错误。添加 gcc 标志 -std=c11-std=c99
  • 编译器永远不会“抛出”(不管是什么意思)或报告这样的错误。那是链接器。并且不管“必须”如何:您绝对应该。过去 20 年的任何现代编码标准都需要这样做。
  • @Olaf 已修复(这实际上已经是关于我的帖子答案的线索)。我的编辑后有机会恢复“重复”标记吗?
  • 我不认为这是不是重复,所以我不会投票重新开放。如果您想详细了解这一点,只需阅读标准或一本好的 C 书,(关于这个主题旧的可能会更好)。否则,只需启用警告,使用支持至少 C99 的现代 C 编译器,这样您就会收到警告,启用所有其他推荐的警告并...使用原型!

标签: c gcc compilation linker undefined-reference


【解决方案1】:

链接您的二进制文件时,除非明确提及,否则您的二进制文件无论如何都会与默认的 C 标准库(例如glibc)链接,其中函数已定义.

所以,当你错过包含声明的头文件时,你最终会得到警告(如果函数原型不匹配note sup>) 但在链接期间,由于默认 C 库的存在,程序成功链接无论如何

根据C11,FWIW 已放弃对隐式函数声明的支持,但大多数编译器支持 不良 行为以保持对旧代码的向后兼容性。


注意:

隐式函数声明: 早些时候,(在 C99、AFAIK 之前),标准没有要求函数具有前向声明。如果一个函数在没有前向声明的情况下使用,则假定它返回 int 并接受任意数量的传入参数。

【讨论】:

  • 我会说“bad 行为”有点强 - 这是 不同 行为。对于遗留代码,不需要原型是一个关键的语言特性,因为只为没有它们编码的函数添加原型是不安全的,因为函数参数的处理方式不同 - 请参阅stackoverflow.com/questions/1255775/…
  • @AndrewHenle 对不起,但我没有明白这一点。在符合标准的同时没有可变参数函数来实现相同的功能吗?我错过了什么?
【解决方案2】:

因为 gcc 会自动将您的代码与 C 库链接。 “未定义对函数的引用”错误通常由 链接器 在无法解析符号时发出,并且仅当在任何链接的库中都找不到符号时才会发生这种情况(顺序链接可能也很重要)。但是默认情况下 C 库是链接的——就好像您将它与 -lc 链接一样。所以,你不会得到那个错误。

如果您告诉 gcc 使用 -nostdlib 链接 C 库,那么您将看到您预期的错误:

$ gcc -nostdlib file.c

另一方面,您应该始终为函数提供原型。

您可能对其他类似的链接器选项感兴趣,例如 -nodefaultlibsnostartfiles 等,您可以在 gcc's manual 中找到这些选项。

【讨论】:

    猜你喜欢
    • 2021-12-27
    • 2022-08-15
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多