为什么我没有 "undefined reference to"?

Why don't I have "undefined reference to"?

我在我的(大)项目中遇到了 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 <string.h> 即可获得 strtok 的原型)确实解决了问题。

然而,由于我的知识匮乏 compiler/linker,我无法理解进程如何接受一个没有原型的函数。 我宁愿期待错误 undefined reference to function 'strtok' ,当您忘记包含正确的 header.

时,这是典型的错误

[编辑] 我明白为什么这个问题被标记为重复,但我确实认为它是不同的:我知道 "good practice" 关于包含,我只是想知道编译器的行为。但是我承认我可以在这个post中找到(部分)我的问题的答案:Are prototypes required for all functions in C89, C90 or C99? or this one: Must declare function prototype in C?

虽然链接您的二进制文件,但除非明确提及,否则您的二进制文件与默认的 C 标准库(例如 glibc)链接,其中函数是已定义.

因此,当您错过包含 声明 的头文件时,您会得到 警告 (如果函数原型有不匹配注意) 但在链接期间,由于默认 C 库的存在,程序已成功链接 anyway.

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


注意:

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

因为 gcc 会自动 link将您的代码与 C 库一起使用。 "undefined reference to function" 错误通常由 linker 无法解析符号时发出,并且仅当无法在任何文件中找到该符号时才会发生库的 linked(linking 的顺序可能也很重要)。但默认情况下,C 库是 link 编辑的——就好像您使用 -lc 编辑它一样 link。所以,你不会得到那个错误。

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

$ gcc -nostdlib file.c

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

您可能对其他类似的 link 选项感兴趣,例如 -nodefaultlibsnostartfiles 等,您可以在 gcc's manual.

中找到它们