Почему в C и C ++ каждый файл .h обычно окружен директивами #ifndef #define #endif? - PullRequest
7 голосов
/ 11 января 2010

Почему каждый файл .h начинается с #ifndef #define #endif? Безусловно, мы можем скомпилировать программу без этих директив.

Ответы [ 5 ]

14 голосов
/ 11 января 2010

Это так называемый «включить охрану». Цель состоит в том, чтобы предотвратить повторный анализ файла, если он включен несколько раз.

4 голосов
/ 11 января 2010

Предотвращает множественные включения одного файла. То же самое можно сделать, используя

#pragma once

директива, но эти #ifndefs являются стандартными, поэтому поддерживаются каждым компилятором.

3 голосов
/ 11 января 2010

Это называется включенным охранником. Вы можете писать без них, пока не начнете писать большие программы и не обнаружите, что вам нужно включать один и тот же файл .h более одного раза, прямо или косвенно, из файла .c. Тогда без включенных защитных устройств вы получите несколько ошибок определения, но с ними содержимое файла заголовка анализируется только один раз и пропускается все последующие разы, избегая этих ошибок. Рекомендуется всегда их использовать.

1 голос
/ 11 января 2010

Если я правильно понимаю, вы хотите знать, может ли при отсутствии включаемых средств защиты многократно включать заголовочный файл ошибку или опасное поведение. Это после исключения нескольких определений и т. Д.

Представьте себе злонамеренного программиста, в заголовочном файле которого нет встроенных средств защиты. Его заголовочный файл определяет один макрос, SZ, который является размером, который вы используете для статически размещенных массивов. Программист может написать свой заголовочный файл так:

#ifndef SZ
#define SZ 1024
#else
#if SZ == 1024
#undef SZ
#define SZ 128
#else
#error "You can include me no more than two times!"
#endif
#endif

Теперь, если вы включите заголовочный файл один раз, вы получите SZ, равный 1024. Если вы включите его дважды, SZ станет 128. Конечно, большинство реальных программистов не являются вредоносными, и никто не пишет код, как указано выше.

Обратите внимание, что стандарт C позволяет assert.h быть #include d более одного раза с различным поведением в зависимости от того, определен ли NDEBUG во время включения assert.h. Итак, assert.h не может иметь охранников. Это особенность, а не ошибка.

0 голосов
/ 11 января 2010

Если заголовочный файл содержит определение типа

int i;
, то, будучи включенным несколько раз без защиты, вызовет ошибку компиляции.
ifndef проверяет, что некоторая переменная препроцессора не определена (и это не так, для первый раз), затем определяет его явно, чтобы избежать повторного захвата. В MSVC вы также можете использовать
#pragma once
вместо ifndef.
...