我在(大)项目中遇到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?
答案 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中找到的-nodefaultlibs
,nostartfiles
等。