.c和.h文件扩展名对C意味着什么?

Ale*_*Mcp 53 c file-type cs50

这一切都在标题中; 我估计超级简单,但在任何地方搜索语法都很难.

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

Ste*_*ini 102

.c:c文件(一般情况下,实际操作的位置)

.h:头文件(包含在预处理器#include指令中).包含通常被认为与代码的其他部分共享的内容,例如函数原型,#define'd stuff,全局变量的extern声明(哦,恐怖)等.

从技术上讲,您可以将所有内容放在一个文件中.一个完整的C程序.百万行.但我们人类倾向于组织事物.所以你创建了不同的C文件,每个文件都包含特定的功能.这一切都很好,干净.然后突然你意识到你在一个给定的C文件中的声明也应该存在于另一个C文件中.所以你会复制它们.因此,最好提取声明并将其放入一个公共文件,即.h

例如,在cs50.h中,您可以找到函数的"前向声明".前向声明是告诉编译器应该如何调用函数(例如,什么是输入参数)以及它返回什么的快速方法,因此它可以执行正确的检查(例如,如果您调用具有错误参数数量的函数,它会抱怨).

另一个例子.假设您编写了一个包含执行正则表达式匹配的函数的.c文件.您希望函数接受正则表达式,要匹配的字符串以及一个参数,该参数指示比较是否必须不区分大小写.

因此,你会放在.c中

bool matches(string regexp, string s, int flags) { the code }
Run Code Online (Sandbox Code Playgroud)

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

0:如果搜索区分大小写

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

并且你想让自己对新标志保持开放,所以你没有放置布尔值.使用数字很难,因此您可以为这些标志定义有用的名称

#define MATCH_CASE_SENSITIVE 0
#define MATCH_CASE_INSENSITIVE 1
Run Code Online (Sandbox Code Playgroud)

此信息进入.h,因为如果任何程序想要使用这些标签,除非您包含信息,否则无法知道它们.当然你可以将它们放在.c中,但是你必须包含.c代码(整个!),这是浪费时间和麻烦的来源.


Sin*_*nür 18

当然,没有任何内容表明头文件.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
Run Code Online (Sandbox Code Playgroud)

  • 这次真是万分感谢!我认为扩展名`.h`和`.c`是强制性的,我从来没有想到过! (3认同)

Jor*_*eña 6

它们不是真正的库文件.它们只是源文件.和Stefano说的那样,.c文件是C源文件,它实际上使用/定义了它在.h文件中头部文件中所概述的实际源文件.头文件通常概述将在实际源文件中使用的所有函数原型和结构.可以把它想象为参考/附录.通过查看头文件可以看出这一点,正如您将看到的那样:)那么当您想要使用在这些源文件中编写的内容时,您#include将获得头文件,其中包含编译器需要知道的信息.

  • 是的,通常就是这样。但是,#include &lt;somefile.h&gt; 通常为编译器附带的文件保留,例如 #include &lt;iostream.h&gt; 您想要的是 #include "cs50.h",并确保它位于编译器可访问的位置,最好是其他源文件所在的位置。 (2认同)