Я никогда не работал с #если, #ifdef, #ifndef, #else, #elif а также #endif.
Когда я просматривал некоторые исходные коды, я нашел широкое применение этих директив.
Чтение некоторых условных препроцессоров, но не нашел подсказки чем они отличаются от обычных условных высказываний.
Поэтому мне было интересно, в чем преимущество следующего кода:
#include<iostream>
int main()
{
int i = 0;
#if i == 0
std::cout<<"This";
#else
std::cout<<"That";
#endif
return 0;
}
через это:
#include<iostream>
int main()
{
int i = 0;
if (i == 0)
std::cout<<"This";
else
std::cout<<"That";
return 0;
}
Кроме того, когда использовать/ неиспользуемый условный препроцессор?
Условный препроцессор работает не так, как в первом примере.
Это работает с константами, понимаете? Во время компиляции он просматривает различные условия и вводит / опускает исходный код в соответствии с ним.
Например:
#define HAS_COMPARISON
int main() {
#ifdef HAS_COMPARISON
int i = 0;
if(i == 0) std::cout << "This";
else
#else
std::cout << "That";
#endif
}
С define
установить, он установит переменную i
и выполнить сравнение … короче, он выведет This
, Если вы прокомментируете это определение, весь блок не будет в вашей программе, что означает, что он всегда будет выводить That
, без установки переменной или сравнения.
Это наиболее распространенное использование определений препроцессора. Вы также можете определить значения и сравнить их, чтобы иметь переменное поведение с тем же определением, но это другая проблема.
Еще раз: условный препроцессор оценивается во время компиляции, переменные условия оцениваются во время выполнения.
Приведенный вами пример не выглядит полезным из-за отсутствия другой информации. Но вот пример, который #if
Полезно.
#if OS == LINUX
//do something
#elif OS == SOLARIS
//do something else
#else
//
#endif
Ключ в том, что #if
оценивается во время компиляции, но if
оценивается при запуске программы.
#if BYTE_ORDER == LITTLE_ENDIAN
//do something
#else
//do something else
#endif
Использование директив препроцессора в этом случае не совсем полезно. Но использование этих директив препроцессора полезно во многих других случаях.
Эти директивы препроцессора могут использоваться для условной компиляции. например Если какая-то программа должна быть разработана для нескольких платформ, то для констант для конкретной платформы могут быть заданы значения. Изменение этих значений может быть выполнено для конкретной платформы, в то время как весь код может поддерживаться как один большой объект.
Это также полезно при отладке. Тестовые модули могут быть скомпилированы в код и запущены с использованием этих условных компиляций во время отладки, и они могут быть остановлены от компиляции с помощью них.
Условная компиляция означает, что код ifdef-out фактически никогда не находится в конечном связанном приложении. Простое использование языковых условных выражений означает, что обе ветки находятся в конечном коде, что делает его больше и потенциально труднее тестировать и т. Д.
использование #ifdef
и т.д., когда вы знаете во время компиляции, что требуется. Языковые условия используются, когда вы не знаете, что вам нужно, до времени выполнения.
Преимущества препроцессора в том, что код выбрасывается. Он не компилируется (что занимает много времени) и не генерирует машинный код, который будет загружен в RAM. Если решение принимается ОЧЕНЬ жестким циклом, работающим ОЧЕНЬ раз, может быть улучшение скорости. Не думайте, что это важно, если вы действительно не примете это время.
Ущерб препроцессора заключается в том, что вы, очевидно, должны знать ответ во время компиляции. Исходный код теперь содержит много кода, который может никогда не исполниться. Человеку становится сложнее отследить, потому что зачастую трудно определить, какими были бы эти значения времени компиляции.