.c 文件何时不应有关联的 .h 文件?

发布于 2024-09-29 18:15:29 字数 115 浏览 3 评论 0原文

大多数时候,在 C 编程中,每个代码文件 (.c) 似乎都会有一个头文件 (.h),至少对于函数原型而言是如此。

什么时候代码文件不适合没有头文件?

Most of the time in C programming it seems that there will be one header file (.h) per code file (.c), for the function prototypes at least.

When would it be appropriate to not have a header file for a code file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

椵侞 2024-10-06 18:15:30

当 .c 文件包含任何代码不需要使用的数据时。

诚然,这种情况很少见,但也有可能发生。例如,我在嵌入式设备中完成了此操作,用启动图形填充视频帧缓冲区。

When the .c file contains data that does not need to be used by any code.

Admittedly this is rare - but it can happen. For example I have done this in embedded devices, to populate the video frame buffer with boot graphics.

回忆凄美了谁 2024-10-06 18:15:30

如果将程序划分为多个模块,通常会有一个“主”模块,其中包含 main() 函数,也许还包含一些其他内容。如果此模块没有任何应该由其他模块调用或使用的内容,则无需在 .h 文件中导出接口。

If you divide your program into a number of modules, there will usually be a "main" module, which contains the main() function and perhaps some other stuff. If this module doesn't have anything that is supposed to be called or used by another module, you don't need to export an interface in a .h file.

£烟消云散 2024-10-06 18:15:30

我认为期望 .c 和 .h 文件之间存在一对一的映射是一个糟糕的开始假设。扔掉它并重新开始。 :D

以不同的方式看待你的问题,你可能会问“什么时候适合创建头文件?”

我将建议以下内容,其中术语“代码模块”是一个或多个相关 .c 文件的一组(通常是一个目录):

  1. 为必须可供其他代码模块使用的公共接口/定义创建标头。
  2. 为必须在代码模块内共享但不能与其他代码模块共享的私有接口/定义创建标头。

这些是您应该需要的唯一头文件。如果这些都不需要,那么您就不需要标头。

一些编码员喜欢人为地将原型/宏/typedefs/等分离到.h中,与.c中的全局变量/函数分开。我建议不要采用这种方法,并建议将所有相关功能放在一个文件中。然后根据需要移动到标头,这些内容对于防止其他 .c 文件中出现“extern”是绝对必要的。

I think expecting a 1-to-1 mapping between .c and .h files is a bad starting assumption. Throw that out and start fresh. :D

Looking at your question differently, you might ask "When is it appropriate to create a header file?"

I'll suggest the following, where the term "code module" is a group (generally a directory) of one or more related .c files:

  1. Create a header for public interfaces/definitions that must be available to other code modules.
  2. Create a header for private interfaces/definitions that must be shared within a code module but not shared with other code modules.

Those are the only header files you should need. If neither of those are required then you don't need a header.

Some coders like to artificially separate prototypes/macros/typedefs/etc into a .h separate from the globals/functions in their .c. I recommend against this approach and suggest having all related functionality in one file. Then move to headers as-needed those things that are absolutely necessary to prevent 'extern's in other .c files.

迷爱 2024-10-06 18:15:30

以防万一,当您不需要 .h 文件中的声明时,但实际上永远不会。

In case, when you wouldn't need the declarations from the .h file, but that is effectively never.

疾风者 2024-10-06 18:15:30

通常,即使我不希望其他代码必须访问它,我也会为“main”创建一个头文件,因为通常(1)调试构建最终会需要主模块外部的某些内容来访问主模块内的某些内容它,或者(2)由于(嵌入式系统)编译器的限制,主模块最终将不得不被分割。让每个 .c 文件包含自己的 .h 文件的模式足够强大,以至于我经常创建几乎空的 .h 文件,即使是定义代码中未引用的内容的 .c 文件(例如中断跳转表) , ETC。)。

当一个文件包含多个程序生成的文件,或包含需要多次编译的文件时,命名约定会变得有点棘手(例如,我的一个项目有两个电机,它们的代码是相同的,只是它们使用不同的 I/O 端口和不同的变量;我的 motor.c 文件包含:

#define LOCK L0
#include "motor.i"
#undef LOCK
#define LOCK L1
#include "motor.i"
#under LOCK

请注意,在这个特定的嵌入式编译器上, -> 运算符效率非常低,因此像这样的语句

  L0.speed++;

将编译为一条指令,而像这样的语句

  L0->speed++;

将转换为五个指令“speed”是结构中的第一项,如果它占据任何其他位置,则为第七项。因此,使用恒定的可解析地址复制代码比使用一个例程同时处理这两个项目更加速度高效,并且在某种程度上更加节省空间。如果

有一个额外的文件与 .c 文件关联,并且它包含实际代码,我将其命名为“.i”,但如果有多个文件该怎么办。

Oftentimes, I'll create a header file for 'main' even if I'm not expecting other code to have to access it, since frequently either (1) a debug build will end up requiring something outside the main module to access something within it, or (2) the main module will end up having to be split due to (embedded system) compiler limitations. The pattern of having every .c file include its own .h file is sufficiently strong that I'll often create nearly-empty .h files even for .c files that define things which aren't referenced in code (like interrupt-jump tables, etc.).

Naming conventions get a little trickier when a file includes multiple program-generated files, or includes files that need to be compiled more than once (e.g. one of my projects has two motors, whose code is identical except that they use different I/O ports and different variables; my motor.c file contains:

#define LOCK L0
#include "motor.i"
#undef LOCK
#define LOCK L1
#include "motor.i"
#under LOCK

Note that on this particular embedded compiler, the -> operator is very inefficient, so a statement like:

  L0.speed++;

will compile to one instructions, while a statement like:

  L0->speed++;

will translate into five instructions if 'speed' is the first item in the structure, or seven if it occupies any other position. It is thus far more speed-efficient, and somewhat more space-efficient, to duplicate code with constant resolvable addresses than to have one routine handle both motors.

If there's one extra file associated with a .c file, and it contains real code, I'll name it ".i". Not sure what to do if there's more than one, though.

不顾 2024-10-06 18:15:29

这有一些用例。最明显的是你的主程序很少需要头文件。

第二个是每个 C 文件没有一个标头。我之前已经将库放在一起(为了这个答案,假设是一个 BTree 库),其中每个单独的函数都位于其自己的源文件中,但有一个库范围的头文件,例如:

btree.h
btree_priv.h
btreeInit.c
btreeDestroy.c
btreeConfig.c

等等。私有头文件用于需要在代码之间共享但不会在 API 中发布的内容。

There's a few use cases for this. The most obvious is that your main program rarely needs a header file.

The second is where you don't have one header for each C file. I've put together libraries before (let's say a BTree library for the purposes of this answer) where each individual function is in its own source file but there's a library-wide header file, something like:

btree.h
btree_priv.h
btreeInit.c
btreeDestroy.c
btreeConfig.c

and so on. The private header file is for stuff that need to be shared between the code but is not to be published in the API.

飘逸的'云 2024-10-06 18:15:29

最明显的是,当 .c 完全独立且不需要其他 .c 文件的原型或 extern 时。这基本上仅适用于非常小的程序,或者那些通过 def 文件导出以插入预定义接口的程序。

most obviously when the .c is fully self contained and does not need to have prototypes or extern's for other .c files. this basically is only for very small programs, or those that export via a def file to plugin in to a predefined interface.

盛夏尉蓝 2024-10-06 18:15:29

我见过大量的代码库,其中单个 .h 文件定义了某些组件的接口,并且多个 .c 文件实现了它。纯粹出于可维护性的原因,该实现被分为几个文件,并在某些逻辑范围内进行了尝试。

有人可能会说,这样的逻辑界限可以用于将组件划分为子组件,从而拥有多个头文件,但设计决策很少是黑白分明的事情,有时这种方法确实有意义。

I have seen massive code bases where a single .h file defines the interface to some component, and several .c files implement it. The implementation was divided into several files purely for maintainability reasons, and was attempted at some logical bounds.

One could argue that such a logical bound could be applied to divide the component into sub-components and consequently have several header files, but design decisions are rarely a black&white affair, and sometimes this approach does make sense.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文