提问人:n0p 提问时间:9/5/2016 最后编辑:Communityn0p 更新时间:9/5/2016 访问量:1844
为什么我没有“未定义的引用”?[复制]
Why don't I have "undefined reference to"? [duplicate]
问:
我在我的(大)项目中遇到了类似的问题。
//# 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
但是,由于我对编译器/链接器的了解不足,我无法理解该过程如何接受尚未原型化的函数。
我宁愿期待错误,这是当您忘记包含正确的标题时的典型错误。undefined reference to function 'strtok'
[编辑]我理解为什么这个问题被标记为重复,但我确实认为它是不同的:我知道关于包含的“良好做法”,我只是想知道编译器的行为。但是,我承认我可以在这篇文章中找到(部分)我问题的答案:C89、C90 或 C99 中的所有功能都需要原型吗? 或者这个: 必须在 C 中声明函数原型?
答:
在链接二进制文件时,除非明确提及,否则二进制文件无论如何都会与默认的 C 标准库(例如)链接,其中定义了函数。glibc
因此,当您错过包含声明的头文件时,您最终会收到警告(如果函数原型有不匹配的注释),但在链接期间,由于默认 C 库的存在,程序无论如何都会成功链接。
FWIW,根据 ,对隐式函数声明的支持已被删除,但大多数编译器都支持不良行为,以保持遗留代码的向后兼容性。C11
注意:
隐式函数声明:早些时候,(在 C99 之前,AFAIK),该标准没有强制要求函数具有正向声明。如果一个函数在没有正向声明的情况下使用,则假定它返回并接受任意数量的传入参数。int
评论
因为 gcc 会自动将您的代码与 C 库链接起来。“未定义的函数引用”错误通常由链接器在无法解析符号时发出,并且仅当在任何链接的库中找不到该符号时才会发生(链接的顺序可能也很重要)。但是 C 库是默认链接的——就好像你用 .所以,你不会得到那个错误。-lc
如果你告诉 gcc 不要使用 链接 C 库,那么你会看到你预期的错误:-nostdlib
$ gcc -nostdlib file.c
另一方面,您应该始终为函数提供原型。
您可能对其他类似的链接器选项感兴趣,例如 等,您可以在 gcc 的手册中找到这些选项。-nodefaultlibs
nostartfiles
评论
-std=c11
-std=c99