为什么我没有“未定义的引用”?

时间:2016-09-05 13:38:45

标签: c gcc compilation linker undefined-reference

我在(大)项目中遇到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的原型)确实解决了这个问题。

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

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

2 个答案:

答案 0 :(得分:3)

链接你的二进制文件时,除非明确提到,否则你的二进制文件与默认的C标准库(例如glibc)相关联,其中函数是定义的< / em>的

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

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

注:

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

答案 1 :(得分:1)

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

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

$ gcc -nostdlib file.c

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

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