Условная компиляция в C и Delphi

Следующий шаблон распространен в коде C:

#ifndef SOMETHING
#define SOMETHING
#endif

Шаблон возможен и в коде Delphi:

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

но это не распространено - я никогда не видел это вообще. Если код Delphi требует условного определения, он просто определяет его без IFNDEF проверять.

Почему так? Какая разница в условной компиляции между C и Delphi, чтобы ifndef проверка нужна для первого и не нужна для последнего?

2 ответа

Решение

Это потому, что это не только распространено, но и обязательно в C:

#include <something.h>

Хотя это редко используется в Delphi. И когда он используется, он на самом деле используется для настройки тех, {$DEFINE} "S:

{$INCLUDE 'something.inc'}

Это важно, потому что DEFINES действительны только при компиляции одного объекта (может быть .PAS файл или .C файл). Delphi использует uses условие, чтобы включить другие единицы, в то время как C использует include включить его заголовки. В C Заголовки могут сами включать другие заголовки. Шаблон, о котором вы спрашиваете, используется для предотвращения рекурсивного повторного включения того же заголовка.

Чтобы сделать материалы кристально чистыми, вот пример того, что можно использовать в C, и эквивалент в Delphi. Допустим, у нас есть 3 файла настройки, где 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 не должна защищать "C" от включения в "A" дважды, потому что она не использует {$INCLUDE} чтобы достичь этой цели, он использует uses заявление. Компилятор получит экспортированные символы из B.dcu файл и C.dcu файлы без риска включения символов из C.dcu дважды.


Другие причины, чтобы увидеть намного больше директив прекомпилятора в коде C:

  • Прекомпилятор намного мощнее, чем Delphi. {$DEFINE} в Delphi-коде рассматривается только условная компиляция, тогда как вариант C может использоваться как для условной компиляции, так и в качестве формы подстановки слов.
  • Обязательное использование #include для заголовков означает, что вы можете иметь заголовок, который определяет макросы. Или вы можете иметь заголовок, который настроен путем указания некоторых #define заявления до фактического #include <header.h>

Этот шаблон НЕ является "общим в C" коде (исходные файлы.c или.cpp). Это часто встречается в файлах заголовков C/C++ (.h):

#ifndef SOMETHING
#define SOMETHING
#endif

Причина состоит в том, чтобы предотвратить случайное включение одного и того же заголовка в НЕСКОЛЬКО РАЗ в один и тот же блок перевода.

Например, предположим, что модуль "ac" использует заголовок "bh". И "bh" # включает в себя "ch". Это означает, что "ac" явно использует "b", а также неявно использует "c". Все идет нормально.

Теперь давайте скажем, что "ch" использует "bh". Материал "#ifndef/#define/#endif" ПРЕДОТВРАЩАЕТ "b" от того, что он # включает в себя ВТОРОЕ ВРЕМЯ (один раз в "a" через "a", второй раз в "a" из "c").

Это все ненужно в Delphi. Delphi "$ifdef" используется только для компиляции условий; Delphi "единицы" заботятся о потенциально рекурсивных и / или циклических зависимостях.

Другие вопросы по тегам