自我背后的理论和用法是什么,包括C和C++中的源文件?

Bud*_*nga 5 c c++ gcc clang visual-c++

请参考此FASTLZ.C源代码.

  • 在第113行和第128行,它包含了自己的源文件.

我认为它的意图是两个定义的关于它们的FASTLZ_LEVEL宏值的函数名称.

#define FASTLZ_COMPRESSOR fastlz1_compress
#define FASTLZ_DECOMPRESSOR fastlz1_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
Run Code Online (Sandbox Code Playgroud)

#define FASTLZ_COMPRESSOR fastlz2_compress
#define FASTLZ_DECOMPRESSOR fastlz2_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
Run Code Online (Sandbox Code Playgroud)

但我无法弄清楚C语言中这个宏背后的理论或关键特性,有人可以简单解释一下这个场景吗?

Pet*_*ead 1

如果使用得当,这可能是一项有用的技术。

假设您有一个复杂的、性能关键的子系统,具有相当小的公共接口和大量不可重用的实现代码。该代码运行了数千行、大约一百个私有函数和相当多的私有数据。如果您使用重要的嵌入式系统,您可能会经常处理这种情况。

您的解决方案可能是分层的、模块化的和解耦的,并且可以通过在不同文件中编码子系统的不同部分来有效地表示和加强这些方面。

有了C,这样做你可能会损失很多。几乎所有工具链都为单个编译单元提供了不错的优化,但对任何声明为 extern 的东西都非常悲观。

如果将所有内容放入一个 C 源模块中,您将得到 -

  • 性能和代码大小改进 - 在许多情况下函数调用将被内联。即使没有内联,编译器也有机会生成更高效的代码。
  • 链接级数据和功能隐藏。
  • 避免名称空间污染及其必然结果 - 您可以使用不太笨重的名称。
  • 更快的编译和链接。

但是,在编辑此文件时,您也会遇到一团糟,并且失去了隐含的模块化性。这可以通过将源代码拆分为多个文件并包含这些文件以生成单个编译单元来克服。

不过,您需要施加一些约定来正确管理它。这些在某种程度上取决于您的工具链,但一些通用的指示是 -

  • 将公共接口放在单独的头文件中 - 无论如何你都应该这样做。
  • 拥有一个包含所有附属 .c 文件的主 .c 文件。这还可以包括公共接口的代码。

  • 使用编译器防护来确保外部编译单元不包含私有头文件和源模块。

  • 所有私有数据和函数都应声明为静态。

  • 保持 .c 和 .h 文件之间的概念区别。这利用了现有的约定。不同之处在于,标头中会有很多静态声明。

  • 如果您的工具链没有强加任何理由不这样做,请将私有实现文件命名为 .c 和 .h。如果您使用包含防护,这些将不会产生任何代码,也不会引入新名称(在链接过程中您可能会得到一些空段)。巨大的优势是其他工具(例如 IDE)将适当地处理这些文件。

  • 问题是询问文件包含*本身*的情况 (4认同)
  • 至少大型编译器 gcc、icc、clang 和 msvc 都支持全程序优化。我还记得几年前在 Oxygen 上使用过旧的 SGI 编译器,它也支持这一点。嵌入式系统的编译器在这方面似乎相当落后。 (2认同)