Условная компиляция в C и Delphi - PullRequest
4 голосов
/ 20 января 2012

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

#ifndef SOMETHING
#define SOMETHING
#endif

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

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

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

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

Ответы [ 2 ]

12 голосов
/ 20 января 2012

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

#include <something.h>

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

{$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. A {$DEFINE} в коде Delphi имеет дело только с условной компиляцией, в то время как вариант C может использоваться как для условной компиляции, так и в качестве формы подстановки слов.
  • Обязательное использование #include для заголовков означает, что вы можете иметь заголовок, который определяет макросы. Или вы можете иметь настроенный заголовок, указав некоторые операторы #define перед фактическим #include <header.h>
3 голосов
/ 20 января 2012

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

...