为什么我需要C头文件?

时间:2013-01-14 01:39:04

标签: c compiler-construction header makefile

我承认,这是一个愚蠢的问题。代码会更好地解释它。得到这些文件:

的hello.c:

#include <stdio.h>

void hello(char * s)
{
    printf("hello, %s\n", s);
}

main.c中:

int main()
{
    hello("world!");
    return 0;
}

生成文件:

test : main.o hello.o
    gcc -o test main.o hello.o

main.o : main.c
    gcc -c main.c

hello.o : hello.c
    gcc -c hello.c

.PHONY : clean
clean :
    -rm test
    -rm main.o
    -rm hello.o

我可以“制作”和“./test”它并且它可以工作。 我不应该在main.c中包含类似hello.h的东西,这样编译器才能知道函数原型吗?

我甚至没有在任何地方包含hello.c它只是工作! main.c怎么知道hello函数?

如果可以,我什么时候需要.h文件?我是C编程的新手,但我认为这个概念很容易掌握,现在我完全糊涂了。

2 个答案:

答案 0 :(得分:13)

如果您使用-Wall标记(并且总是使用它,以及-Werror -Wextra),那么您将收到以下消息:

main.c: In function 'main':
main.c:3: warning: implicit declaration of function 'hello'

编译器有效地“猜测”该做什么,这可能在许多情况下导致灾难。

正确使用头文件可以避免这种警告。

答案 1 :(得分:4)

您不需要头文件;相反,您的功能需要原型。当你致电hello传递"world"时,C会发现你正在调用char*的单参数函数,并且一切正常。但是,如果函数采用浮点数,并且你决定给它int(尝试它,它非常有启发性),这将不起作用。出于向后兼容的原因,C将允许您在没有原型的情况下调用函数,但这很危险。例如,如果调用hello,编译器会认为您正在调用返回int的函数。从技术上讲,您正在调用未定义的行为,因此您的程序是偶然的。

标题恰好提供了提供原型的最便捷方式,但您可以在代码中提供它们,如下所示:

void hello(char*);

int main()
{
    hello("world!");
    return 0;
}