#ifndef SOMETHING
#define SOMETHING
#endif
该模式在Delphi代码中也是可能的:
{$IFNDEF SOMETHING}
{$DEFINE SOMETHING}
{$ENDIF}
但这并不常见 - 我根本没有见过。如果一个 Delphi 代码需要条件定义,它只需定义而不需要使用 IFNDEF
检查。
为什么呢?C 和 Delphi 之间的条件编译有什么区别,以至于前者需要 ifndef
检查而后者却不需要呢?
#ifndef SOMETHING
#define SOMETHING
#endif
{$IFNDEF SOMETHING}
{$DEFINE SOMETHING}
{$ENDIF}
但这并不常见 - 我根本没有见过。如果一个 Delphi 代码需要条件定义,它只需定义而不需要使用 IFNDEF
检查。
为什么呢?C 和 Delphi 之间的条件编译有什么区别,以至于前者需要 ifndef
检查而后者却不需要呢?
这是因为这不仅在C语言中很常见,而且是强制性的:
#include <something.h>
虽然Delphi很少使用这个,但当被使用时,实际上是用来设置那些{$DEFINE}
的:
{$INCLUDE 'something.inc'}
这很重要,因为宏定义(DEFINES)只在编译一个对象时有效(无论是.PAS
文件还是.C
文件)。Delphi使用uses
语句来包含其他单元,而C使用include
语句来包含头文件。在C中,头文件本身可能会包含其他头文件。你所询问的模式用于防止递归重新包含同一头文件。
为了让事情更加清晰明了,这里有一个在C中使用的示例以及相应的Delphi示例。假设我们有一个包含三个文件的设置,其中A
需要包含B
和C
,而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
如果没有C.h
中的条件定义,C.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版本不需要保护"A"中的"C"重复被包含,因为它没有使用{$INCLUDE}
来实现这个目标,而是使用uses
语句。编译器将从B.dcu
文件和C.dcu
文件获取导出符号,没有包含C.dcu
两次的风险。
{$DEFINE}
仅处理条件编译,而C变体可用于条件编译和作为一种单词替换形式。#include
意味着您可以有一个定义宏的头文件。或者您可以通过在实际的#include <header.h>
之前指定一些#define
语句来配置头文件。#ifndef
来防止头文件递归,但这似乎不是C语言中#ifndef
的唯一用途。我已经看到很多次在没有后续#include
的情况下使用#ifndef
。 - kludgC.h
文件没有任何INCLUDE,但是如果没有IFNDEF保护,它将在A.h
中被包含两次。 - Cosmin Prund#ifndef
不仅仅是用于防止头文件递归,尽管这可能是 #ifndef
最重要的用途。我还认为,在 C 语言中,#ifndef
的重要性与广泛使用头文件(*.h)有关,而它们的 Delphi 类似物(*.inc 文件)很少使用且目的非常有限。 - kludg这种模式在C代码(.c或.cpp源文件)中并不常见。它在C/C++头文件(.h)中很常见:
#ifndef SOMETHING
#define SOMETHING
#endif
原因是为了防止同一个头文件在同一翻译单元中无意中包含多次。
例如,假设模块"a.c"使用了头文件"b.h",而"b.h" #include's "c.h"。这意味着"a.c"显式地使用了"b",隐式地也使用了"c"。目前为止,一切正常。
现在假设"c.h"也使用了"b.h"。"#ifndef/#define/#endif"的东西可以防止“b”被重复# include'd(一次在"a"中由"a",第二次在"c"从"a"中)。
在Delphi中这一切都是不必要的。Delphi中"$ifdef"仅用于条件编译;Delphi中的“单元”负责处理潜在的递归和/或循环依赖关系。