C 中的每个函数都应该有自己的 .c 文件吗?或者我可以将程序的所有功能放在一个 .c 文件中吗?

Should every function in C have its own .c file ? or can i put all the functions of my program in one .c file?

我是 C 编程新手,刚开始学习函数。 我应该将每个函数放在一个 .c 和 .h 文件中,还是可以将所有函数和 headers 放在一个 .c 和 .h 文件中? 谢谢。

不!根本没有必要这样做。那会严重影响你的表现。

通常我们只倾向于创建新文件 .h 来存储 functions/methods 我想我们想在其他项目或程序中重复使用。

你的程序应该是这样的:

我们称这个为prog1.c

#include <only libs that you need>

    void functionA (parameterType parameter){
        //Whatever your function needs to do
    }
    int main(){
       //this is your main function and where the program will start working.
       functionA(parameters) /*Here is how you call functionA if it's void giving it's needed parameters.*/
    }

稍后,随着知识的增加,您将了解何时需要将函数存储或不存储在其他文件中以学习和保持组织有序。现在没有那个必要了。您应该最专注于了解它们如何工作以及如何相互沟通。

如果您需要在其他文件中使用 functionA,那么您只需包含该 .c 文件,如下所示:

在 prog2.c 中,您可以通过调用

来启动它
#include "prog1.c"

Should every function (definition) in C have its own .c file?

没有。 不应该,但是可以。这是编码风格的问题,但它不是首选的方式,也不常见。它增加了编译和 linking 时间。


Or can I put all the function (definitions) of my program in one .c file?

是的,你可以。再说一次,自己的编码风格问题。

如果您的代码中有很多或多个函数,您还可以将函数定义分组到自己的 .c 文件中,然后在调用编译器时将这些文件分组到 link 文件中。

这样你就可以保持清晰。

一种方法是将所有函数定义保存在一个单独的 .c 文件中,除了 main.c,其中包含 main 函数。


Should I put each function in a .c and .h file?

函数定义不能放在.h个文件中。

.h仅包含函数和其他变量声明,以及宏定义。

函数定义需要放在 .c 个文件中。

如果您打算将每个函数定义放入一个自己的 .c 文件中,并将每个函数声明放入一个自己的 .h 文件中,则绝对不需要。

它甚至会让你一路上都感到困惑。

你其实可以这样做,但绝对不推荐。


Or can I put all of the functions and headers in one .c and .h file ?

在这里您不能 将函数定义放在.h 文件中。

但是您可以将所有函数定义打包到一个 .c 文件中,并将所有函数声明打包到一个 .h 文件中。

决定将代码的不同部分放在哪里是您个人和编程语言经验所带来的事情。考虑到您提到您目前正在学习函数,让我回顾一下决定将函数放在哪里的几个主要因素。

原型


在编写代码时,在使用变量之前,需要先声明它。功能也是如此。第一种简单的方法是在使用之前定义一个函数。

int add(int a, int b) {
    return a + b;
}

int main(void) {
    int result = add(10, 8);
    return 0;
}

这里我定义了一个函数add(),并在函数main()中调用。这段代码将简单地编译并运行。但是,如果我将 add() 函数的定义放在 main() 函数下方会怎么样?

int main(void) {
    int result = add(10, 8);
    return 0;
}

int add(int a, int b) {
    return a + b;
}

这段代码会导致编译错误。编译器不知道我在 main() 函数中调用了哪个 add() 函数,因为还没有定义 add() 函数。有时您可以通过简单地重新排列代码来解决这个问题。其他时候这是不可能的,这就是原型设计发挥作用的原因。

int add(int a, int b);

int main(void) {
    int result = add(10, 8);
    return 0;
}

int add(int a, int b) {
    return a + b;
}

这告诉编译器有一个函数 add() 接受两个 int 参数,稍后将在代码中定义。编译器很满意,确实 - 这段代码再次编译没有问题。

#include 指令


在 C 中包含头文件有点麻烦。它是 包括 头文件定义的方法,在你的 .c 文件中,它以最简单的方式完成 - 你的 C 代码中的每个 #include <my_header.h> 指令在 编译之前被 my_header.h 文件 的所有内容替换。例如假设以下文件:

my_header.h

// Hello, I am the my_header.h file
// I currently have no definitions

my_program.c

#include "my_header.h"

int main(void) {
    // Do nothing
    return 0;
}

如果我只编译 my_program.c,预处理器将在编译器之前检查文件。它会找到一个 #include 指令,寻找一个名为 my_header.h 的文件,找到它并将其内容复制到 .c 文件中,就像这样:

// Hello, I am the my_header.h file
// I currently have no definitions

int main(void) {
    // Do nothing
    return 0;
}

然后将生成的文件提供给编译器。

虽然这种方法非常简单且易于实施,但它使 C 非常容易出错并且难以维护,除非非常小心。例如,这就是 include guards 存在的原因。假设您在主文件中包含两个文件。现在这两个文件都包含一个,第三个文件。完成所有替换后,您最终会将第三个文件粘贴到代码中两次,这将导致编译期间发生命名冲突。

这也意味着您在技术上 可以 将任何类型的代码放入头文件中。然而,在我的整个职业生涯中,我只遇到过一个这样的代码是可以接受的案例(在裸机嵌入式系统程序中),所以我不能强调这一点——除非你真的、真的知道你在做什么, 永远不要在头文件中放置除函数原型、变量声明、包含和宏之外的任何内容。否则,最容易导致代码以最莫名其妙的方式中断。

结论


我最常看到(并且个人也遵循)的风格是将具有相似功能的函数集分离到单独的 .c 文件中。此 .c 文件不包含任何内容,但包含函数定义(即代码)和此 .c 文件关联的头文件的单个 #include 指令。这将所有功能保存在单独的 translation unit.

带有include guards的头文件(当你不在任何地方多次包含该文件时不需要,但习惯是一个好习惯)包含所有必需的#include 系统库指令、项目中的其他头文件以及相应 .c 文件中每个函数的函数原型。每当您需要在别处使用这些函数时,请将此头文件包含在任何其他头文件中。通常使用 <> 包含系统库,而使用 "".

包含您自己的文件

如其他答案所述,包含主要功能的 .c 文件通常可以在没有相应头文件的情况下存在。所有其他 .c 文件都应该有一个关联的头文件。这主要符合 Google's C++ Style Guide.

一个例子


对于任何较小的项目,您很可能只需要两个文件。以这些为例:

main.h

#ifndef _MAIN_H_
#define _MAIN_H_

#include <stdio.h>
// any other includes

int add(int a, int b);
int sub(int a, int b);

int main(int argc, char *argv[]);

#endif // _MAIN_H_

main.c

#include "main.h"

int main(int argc, char *argv[])
{
    int first = 10;
    int second = 8;
    int third, fourth;

    third = add(first, second);
    fourth = sub(third, first);

    return 0;
}

int add(int a, int b)
{
    return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

如果您要添加更多数学函数,比如 mul()div(),将它们全部从 main.c 文件中取出并创建一个新的 文件 - my_math.cmy_math.h 沿途的一些东西,遵循与项目其余部分相同的规则。然后,要在主函数中调用 mul() 函数,您需要在 main.h.

中调用 #include my_math.h

很多都是经验带来的。随意探索其他样式并尝试最适合您的样式。所有这一切中最重要的部分是保持一致。选择一种风格并坚持下去。祝你学业顺利!