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

.c和.h文件扩展名对c意味着什么?,c,file-type,cs50,C,File Type,Cs50,都在书名里;我想这很简单,但在任何地方都很难找到语法上的东西 这是我从中复制的两个库文件,我想知道为什么它们有两个不同的扩展名。.c:c文件(实际操作通常在这里) .h:头文件(包含在预处理器#include指令中)。包含通常被认为与代码的其他部分共享的内容,如函数原型、定义的内容、全局变量的外部声明(哦,恐怖)等等 从技术上讲,您可以将所有内容都放在一个文件中。一个完整的C程序。百万行。但我们人类倾向于组织事物。因此,您可以创建不同的C文件,每个文件都包含特定的函数。这些都很好,很干净。然后你

都在书名里;我想这很简单,但在任何地方都很难找到语法上的东西

这是我从中复制的两个库文件,我想知道为什么它们有两个不同的扩展名。

.c:c文件(实际操作通常在这里)

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

从技术上讲,您可以将所有内容都放在一个文件中。一个完整的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代码(完整!),这既浪费时间,也会带来麻烦。

源文件是.c,源文件是.h


通常,
.c
文件包含实现,
.h
文件包含实现的“接口”。

它们不是真正的库文件。它们只是源文件。正如Stefano所说,.c文件是c源文件,它实际使用/定义了它仅在.h文件(头文件)中概述的内容的实际来源。头文件通常概述将在实际源文件中使用的所有函数原型和结构。把它想象成一个参考/附录。这在查看头文件时很明显,正如您将看到的:)因此,当您想要使用这些源文件中编写的内容时,您可以
#包括
头文件,其中包含编译器需要知道的信息。

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


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

当然,没有规定头文件的扩展名必须是
.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
E:\Temp>键入my.interface
#如果包括我的界面
#定义MYBUFFERSIZE 8
#定义包含的我的界面
#恩迪夫
E:\Temp>键入my.source
#包括
#包括“my.interface”
内部主(空){
char x[MYBUFFERSIZE]={0};
x[0]=“a”;
看跌期权(x);
返回0;
}
E:\Temp>gcc-x c my.source-o my.exe
E:\Temp>my
A.

很好的澄清,谢谢。所以我#include,但这反过来又从cs50.c调用它需要的实际函数。这是我从阅读文件中得出的结论,对吗?是的,通常是这样的。但是,#include通常是为编译器附带的文件保留的,比如#include What you want is#include“cs50.h”,并确保它位于编译器可以访问的地方,最好是在其他源文件所在的地方。如果我没记错,不鼓励使用“”。yu应始终正确使用和调整-I。@Stefano Borini请参见6.10.2:include“q-char-sequence”新行形式的预处理指令
会导致该指令被
分隔符。以实现定义的方式搜索命名的源文件。如果不支持此搜索,或者搜索失败,则将重新处理指令,就像它读取
#include new line
一样,这也可能有帮助:这也可能有帮助:。有很多相同之处,但解释方式略有不同。谢谢!我原以为扩展名
.h
.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