为什么即使缺少头文件,我也能成功编译程序?

时间:2011-10-09 09:57:58

标签: c compilation strtok

当我学习“strtok”功能时,我发现了一个奇怪的问题。 起初我在编写演示程序时错过了一个头文件,如下所示:

/* strtok example */
#include <stdio.h>
//#include <string.h> // the header file I've missed at first

int main ()
{
    char str[] ="- This, a sample string.";
    char * pch;
    printf ("Splitting string \"%s\" into tokens:\n",str);
    pch = strtok (str," ,.-");
    while (pch != NULL)
    {   
        printf ("%s\n",pch);
        pch = strtok (NULL, " ,.-");
    }   
    return 0;
}

编译器没有给出任何错误消息并成功编译了程序。但它在运行时会导致分段错误。当我添加丢失的头文件时,一切都进展顺利。

我的问题是为什么编译器没有诊断第一次编译的任何错误。我使用gcc4.2.1在Mac OS X下编译它。

2 个答案:

答案 0 :(得分:4)

在C中,允许函数没有原型(声明)。调用这些函数时不会有参数转换。例如:

f(0);
即使未声明f

也会使用参数(int)0调用名为f的函数。当f(在另一个.c文件中或在库中)的实际定义是例如时,这会导致未定义的行为(...段错误...)。 int f(char*)int f(long)。这不是一种好的做法,但保留了与原始C的向后兼容性。

当原型出现时,编译器会在调用站点自动将参数转换为所需类型(可能发出错误)。

PS:不要错误地认为int是默认值。编译器实际调用的内容完全取决于调用参数。例如。 f(1.1)void f(double)匹配,f("string")f(char*)匹配。

答案 1 :(得分:4)

  

我的问题是为什么编译器在第一次编译时没有给出任何错误信息。

因为您没有使用-Wall -Wextra进行编译。对于新编写的现代代码,您当然应该这样做。