4

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

#ifndef SOMETHING
#define SOMETHING
#endif

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

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

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

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

4

2 回答 2

12

这是因为这在 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

如果没有条件定义 in C.hC.h文件最终会被包含在A.h. 这是代码在 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 代码中的 A{$DEFINE}仅处理条件编译,而 C 变体可用于条件编译和作为单词替换的一种形式。
  • 强制使用#includefor 标头意味着您可以拥有一个定义宏的标头。#define或者您可以通过在实际之前指定一些语句来配置标题#include <header.h>
于 2012-01-20T06:50:08.870 回答
3

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

#ifndef SOMETHING
#define SOMETHING
#endif

原因是为了防止 SAME 标头无意中在同一个翻译单元中包含 MULTIPLE TIMES。

例如,假设模块“ac”使用头文件“bh”。和“bh”#include 的“ch”。这意味着“ac”明确使用“b”,也隐含使用“c”。到目前为止,一切都很好。

现在假设“ch”使用“bh”。“#ifndef/#define/#endif”的东西防止“b”第二次被#include'd(一次在“a”中被“a”,第二次在“a”中被“c”)。

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

于 2012-01-20T06:59:46.837 回答