这一切都在标题中;我认为超级简单,但在任何地方搜索语法都很难。
这是我正在从CS50.net复制的两个库文件,我想知道他们为什么有两个不同的扩展名。
答案 0 :(得分:94)
.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 }
现在,假设您要传递以下标志:
0:如果搜索区分大小写
1:如果搜索不区分大小写
你想让自己对新旗帜保持开放,所以你没有放一个布尔值。 玩数字很难,所以你为这些标志定义有用的名称
#define MATCH_CASE_SENSITIVE 0
#define MATCH_CASE_INSENSITIVE 1
此信息进入.h,因为如果任何程序想要使用这些标签,除非您包含该信息,否则无法知道它们。当然你可以将它们放在.c中,但是你必须包含.c代码(整个!),这是浪费时间和麻烦的来源。
答案 1 :(得分:16)
当然,没有任何内容表明头文件的扩展名必须为.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
答案 2 :(得分:5)
他们不是真正的库文件。它们只是源文件。与Stefano一样, .c 文件是C源文件,它实际上使用/定义了它在 .h 文件(头文件)中仅列出的实际来源。头文件通常概述将在实际源文件中使用的所有函数原型和结构。可以把它想象为参考/附录。通过查看头文件可以看出这一点,正如您将看到的那样:)那么当您想要使用在这些源文件中编写的内容时,您#include
头文件,其中包含编译器将使用的信息需要知道。
答案 3 :(得分:2)
.c是源文件,.h是header file。
答案 4 :(得分:1)
.c文件是将被编译的源文件。 .h文件用于将程序的API公开给该程序的其他部分或其他程序是否正在创建库。
例如,程序PizzaDelivery可以包含主程序的1 .c文件和包含实用程序功能的1 .c文件。现在,为了能够使用实用程序函数的程序的主要部分,您需要通过函数原型将API公开到.h文件中,此.h文件包含在主.c文件中。
答案 5 :(得分:0)
.c : 'C' source code
.h : Header file
通常,.c
文件包含实现,.h
文件包含实现的“接口”。