Условная компиляция в 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 "единицы" заботятся о потенциально рекурсивных и / или циклических зависимостях.