“.c”和“.h”文件扩展名对C语言有什么意义?

81

标题已经说明了一切;我认为非常简单,但是在任何地方搜索语法内容都很困难。

这是两个库文件,我正在从CS50.net复制它们,并且我想知道它们为什么有两个不同的扩展名。

6个回答

138

.c:C文件(通常是真正的行动发生的地方)

.h:头文件(可以通过预处理器#include指令进行包含)。包含通常被认为与代码的其他部分共享的内容,如函数原型、#define的东西、全局变量的外部声明(啊,可怕)等。

从技术上讲,你可以把所有东西都放进一个单一的文件中。整个C程序。百万行。但我们人类倾向于组织事物。因此,你创建不同的C文件,每个文件包含特定的函数。这很好,也很干净。然后突然你意识到,你在某个C文件中有一个声明应该存在于另一个C文件中。所以你会重复它们。最好的方法是提取声明并将其放入公共文件中,即.h文件。

例如,在cs50.h中,你会找到称为“前向声明”的函数声明。前向声明是告诉编译器如何调用函数的快捷方式(例如输入参数是什么),以及它返回什么,这样它就能执行适当的检查(例如如果你使用错误数量的参数调用一个函数,它就会抱怨)。

另一个例子。假设你写了一个.c文件,其中包含一个执行正则表达式匹配的函数。你希望函数接受正则表达式、要匹配的字符串以及一个参数,告诉函数是否对比要忽略大小写。

在.c文件中,你将放置:

bool matches(string regexp, string s, int flags) { the code }

现在,假设您想传递以下标志:

0:如果搜索区分大小写

1:如果搜索不区分大小写

而且您希望保持对新标志的开放性,因此没有使用布尔值。由于处理数字很困难,因此您为这些标志定义了有用的名称。

#define MATCH_CASE_SENSITIVE 0
#define MATCH_CASE_INSENSITIVE 1

这些信息需要放在.h文件中,因为如果其他程序想要使用这些标签,除非你在其中包含这些信息,否则它们无法知道它们的存在。当然你可以把它们放在.c文件中,但是那样你就需要包含整个.c代码,这是浪费时间和麻烦的源泉。


这也许会有所帮助:https://dev59.com/a3A75IYBdhLWcg3wFE2b。很多内容相同,但解释方式略有不同。 - spugm1r3

25

当然,并没有什么规定头文件的扩展名必须是 .h,C语言源代码的扩展名必须是 .c。这些只是有用的约定。

E:\Temp> type my.interface
#ifndef MY_INTERFACE_INCLUDED
#define MYBUFFERSIZE 8
#define MY_INTERFACE_INCLUDED
#endif

E:\Temp> type my.source
#include <stdio.h>

#include "my.interface"

int main(void) {
    char x[MYBUFFERSIZE] = {0};
    x[0] = 'a';
    puts(x);
    return 0;
}

E:\Temp> gcc -x c my.source -o my.exe

E:\Temp> my
a

4
谢谢您!我以为扩展名“.h”和“.c”是必需的,从来没有想过其他的可能性! - KeyC0de

6

它们实际上并不是库文件,只是源文件。就像Stefano所说的那样,.c文件是C源代码文件,它实际使用/定义了.h文件中仅概述的实际源代码。头文件通常概述了在实际源文件中将要使用的所有函数原型和结构。可以把它看作参考/附录。当查看头文件时,这一点显而易见:)因此,当您想要使用这些源文件中编写的内容时,您需要 #include 头文件,其中包含编译器需要知道的信息。


好的解释,谢谢。所以我使用#include <cs50.h>,但是它会从cs50.c中调用它需要的实际函数。这是我从阅读文件中得出的结论,这正确吗? - Alex Mcp
2
是的,通常情况下就是这样。然而,#include <somefile.h> 通常是为了编译器自带的文件,比如 #include <iostream.h>。你需要的是 #include "cs50.h",并确保它在编译器可访问的地方,最好是在其他源文件所在的位置。 - Jorge Israel Peña
如果我没记错的话,不鼓励使用 ""。你应该始终使用 <> 并适当调整 -I。 - Stefano Borini
1
@Stefano Borini 请查看6.10.2:形如 # include "q-char-sequence" new-line 的预处理指令会导致该指令被指定序列之间的 " 分隔符所标识的源文件的整个内容替换。命名的源文件以实现定义的方式进行搜索。如果不支持此搜索或搜索失败,则将重新处理该指令,就好像它读取了 # include <h-char-sequence> new-line - Sinan Ünür

4

.c 文件是源代码文件,而 .h 文件则是头文件


1

.c文件是源代码文件,将被编译。.h文件用于将程序的API公开给该程序的其他部分或您正在创建库的其他程序。

例如,程序PizzaDelivery可能有一个包含主程序的.c文件和一个包含实用函数的.c文件。现在,为了使程序的主要部分能够使用实用函数,您需要通过函数原型公开API到.h文件中,这个.h文件被主.c文件包含。


0
.c : 'C' source code
.h : Header file

通常情况下,.c 文件包含实现代码,而 .h 文件则包含实现的“接口”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接