C 和 Delphi 中的条件编译

发布于 2024-12-27 21:26:19 字数 333 浏览 3 评论 0原文

下一个模式在 C 代码中很常见:

#ifndef SOMETHING
#define SOMETHING
#endif

该模式在 Delphi 代码中也是可能的:

{$IFNDEF SOMETHING}
{$DEFINE SOMETHING}
{$ENDIF}

但它并不常见 - 我从来没有见过它。如果 Delphi 代码需要条件定义,它只是定义它而不进行 IFNDEF 检查。

为什么会这样呢? C和Delphi的条件编译有什么区别,前者需要ifndef检查而后者不需要?

The next pattern is common in C code:

#ifndef SOMETHING
#define SOMETHING
#endif

The pattern is possible in Delphi code too:

{$IFNDEF SOMETHING}
{$DEFINE SOMETHING}
{$ENDIF}

but it is not common - I have never seen it at all. If a Delphi code requires a conditional define, it just defines it without IFNDEF check.

Why so? What is the difference in conditional compilation between C and Delphi so that ifndef check is needed for former and not needed for latter?

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

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

发布评论

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

评论(2

小情绪 2025-01-03 21:26:19

这是因为这在 C 中不仅常见而且是强制的:

#include <something.h>

而在 Delphi 中很少使用。使用时,它实际上用于设置那些 {$DEFINE}

{$INCLUDE 'something.inc'}

这很重要,因为 DEFINES 仅在编译一个对象时有效(可能是 .PAS文件或 .C 文件)。 Delphi 使用 uses 子句来包含其他单元,而 C 使用 include 来包含其标头。在 C 标头中,标头本身可能包含其他标头。您所询问的模式用于防止递归地重新包含相同的标头。

为了让事情变得一目了然,这里有一个可以在 C 中使用的示例,以及 Delphi 中的等效示例。假设我们有 3 个文件设置,其中 A 需要同时包含 BC,以及 B > 只需要包含C。 “C”文件将如下所示:

// ----------------------- A.h
#ifndef A
#define A

#include "B.h"
#include "C.h"

// Stuff that goes in A

#endif

// ------------------------ B.h
#ifndef B
#define B

#include "C.h"

// Stuff that goes in B

#endif

// ----------------------- C.h
#ifndef C
#define C

// Stuff that goes in C

#endif

如果没有 Ch 中的条件定义,Ch 文件最终将被包含在 Ah 中两次。这就是代码在 Delphi 中的样子:

// --------------------- A.pas
unit A;

interface

uses B, C;

implementation

end.

// --------------------- B.pas
unit B

interface

uses C;

implementation

end.

// --------------------- C.pas

unit C

interface

implementation

end.

Delphi/Pascal 版本不需要保护“C”不被包含在“A”中两次,因为它不使用 {$INCLUDE} 为了实现这个目标,它使用 uses 语句。编译器将从 B.dcu 文件和 C.dcu 文件获取导出的符号,而不存在包含来自 C.dcu 的符号的风险两次。


在 C 代码中看到更多预编译器指令的其他原因:

  • 预编译器比 Delphi 的强大得多。 Delphi 代码中的 {$DEFINE} 仅处理条件编译,而 C 变体既可用于条件编译,也可作为单词替换的一种形式。
  • 标头强制使用 #include 意味着您可以拥有定义宏的标头。或者,您可以通过在实际的 #include 之前指定一些 #define 语句来配置标头

That's because this is not only common but mandatory in C:

#include <something.h>

While this is rarely used in Delphi. And when used, it's actually used to set up those {$DEFINE} 's:

{$INCLUDE 'something.inc'}

This matters because DEFINES are only valid while compiling one object (may it be a .PAS file or a .C file). Delphi uses the uses clause to include other units, while C uses the include to include it's headers. In C headers might themselves include other headers. The pattern you're asking about is used to prevent recursively re-including the same header.

To make maters crystal-clear, here's a sample of what one might use in C, and the equivalent in Delphi. Let's say we've got a 3 files setup, where A needs to include both B and C, and B only needs to include C. The "C" files would look like this:

// ----------------------- A.h
#ifndef A
#define A

#include "B.h"
#include "C.h"

// Stuff that goes in A

#endif

// ------------------------ B.h
#ifndef B
#define B

#include "C.h"

// Stuff that goes in B

#endif

// ----------------------- C.h
#ifndef C
#define C

// Stuff that goes in C

#endif

Without the conditional defines in C.h, the C.h file would end up being included twice in A.h. This is how the code would look like in Delphi:

// --------------------- A.pas
unit A;

interface

uses B, C;

implementation

end.

// --------------------- B.pas
unit B

interface

uses C;

implementation

end.

// --------------------- C.pas

unit C

interface

implementation

end.

The Delphi/Pascal version doesn't need to protect "C" from being included twice in "A" because it doesn't use the {$INCLUDE} to achieve this goal, it use the uses statement. The compiler would get the exported symbols from the B.dcu file and the C.dcu files with no risk of including symbols from C.dcu twice.


Other reasons to see a lot more precompiler directives in C code:

  • The precompiler is a lot more powerful then Delphi's. A {$DEFINE} in Delphi code only deals with conditional compilation, while the C variant can be used for both conditional compilation and as a form of word substitution.
  • The mandatory use of #include for headers means you can have a header that defines macros. Or you can have a header that's configured by specifying some #define statements before the actual #include <header.h>
疾风者 2025-01-03 21:26:19

此模式在“C”代码(.c 或 .cpp 源文件)中并不常见。它在 C/C++ 标头 (.h) 文件中很常见:

#ifndef SOMETHING
#define SOMETHING
#endif

原因是为了防止同一标头无意中在同一翻译单元中包含多次。

例如,假设模块“ac”使用标头“bh”。和“bh”#include 的“ch”。这意味着“ac”显式使用“b”,并且隐式也使用“c”。到目前为止,一切都很好。

现在假设“ch”使用“bh”。 “#ifndef/#define/#endif”内容可以防止“b”第二次被#include(一次是“a”在“a”中,第二次是“c”在“a”中)。

这在Delphi 中都是不必要的。 Delphi“$ifdef”仅用于条件编译; Delphi“单元”负责潜在的递归和/或循环依赖。

This pattern is NOT "common in C" code (.c or .cpp source files). It's common in C/C++ headers (.h) files:

#ifndef SOMETHING
#define SOMETHING
#endif

The reason is to prevent the SAME header from being inadvertantly including MULTIPLE TIMES in the same translation unit.

For example, let's say module "a.c" uses header "b.h". And "b.h" #include's "c.h". That means "a.c" explicitly uses "b", and implicitly also uses "c". So far, so good.

Now let's say that "c.h" uses "b.h". The "#ifndef/#define/#endif" stuff PREVENTS "b" from being #include'd a SECOND TIME (once in "a" by "a", the second time in "a" from "c").

This is all unnecessary in Delphi. Delphi "$ifdef" is used only for condition compilation; Delphi "units" take care of potentially recursive and/or circular dependencies.

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