#if vs #ifndef vs #ifdef
Моя проблема в первую очередь, понимание #ifndef
а также #ifdef
, Я также хочу понять разницу между #if
, #ifndef
, а также #ifdef
, Я это понимаю #if
в основном, если утверждение. Например:
#include<iostream>
#define LINUX_GRAPHICS 011x101
int main(){
long Compare = LINUX_GRAPHICS;
#if Compare == LINUX_GRAPHICS
std::cout << "True" << std::endl;
#endif
}
Но остальные, хотя я читал о них, я не могу понять. Они также выглядят как очень похожие термины, но я сомневаюсь, что они работают одинаково. Помощь будет принята с благодарностью.
5 ответов
Макросы расширяются препроцессором, который ничего не знает о значениях переменных во время выполнения. Речь идет только о текстовой замене (или сравнении символов, известных препроцессору). Ваша линия
#if Compare == LINUX_GRAPHICS
будет расширяться до
#if Compare == 011x101
и так как "Сравнить" отличается от "011x101", оно оценивается как ложное. На самом деле я даже не уверен на 100% в этом, но дело в том, что вы смешиваете директивы препроцессора с переменными, которые оцениваются во время выполнения. Это бессмысленно. Директивы препроцессора не заменяют операторы C++.
Для большинства традиционных случаев использования макросов в настоящее время есть лучший способ. Если вам действительно не нужно использовать макросы, лучше их не использовать. Это крайне затрудняет чтение кода (например, я не понимаю, как работают эти макросы в вашем коде, и, если мне это действительно не нужно, я не хочу знать:P), и существуют другие проблемы с макросами, которые могут привести к очень сложным чтобы найти ошибки в вашей программе. Перед использованием макросов я бы посоветовал вам сначала рассмотреть вопрос о том, не существует ли более естественного способа C++ для достижения того же самого.
PS:
#ifdef SYMBOL
ifdef = "if defined"
this part of the code is excluded before the compiler even sees it
if SYMBOL is not defined (via #define)
#endif
#ifndef SYMBOL
ifndef = "if not defined"
this part of the code is excluded before the compiler even sees it
if SYMBOL is defined (via #define)
#endif
Я написал "исключено" с целью подчеркнуть негативное влияние, которое это оказывает на читабельность вашего кода. Если вы злоупотребляете #ifdef
или же #ifndef
внутри обычных блоков кода это будет чрезвычайно трудно читать.
#if
не имеет никакого представления о Compare
или значение, которое он содержит, так что он, вероятно, не делает то, что вы намеревались.
Помните, что препроцессор выполняет простую замену текста.
Заявление будет расширяться, как видно из #if
как
#if Compare == 011x101
и расширяется как
#if 0 == 011x101
что, конечно, не даст true
на этапе предварительной обработки.
#ifdef
а также #ifndef
директивы проверяют, был ли символ препроцессора #define
вообще, либо используя эту (<-) директиву препроцессора, либо опцию препроцессора вашего компилятора (чаще всего -D<preprocessor-symbol>
).
Их не волнует, содержит ли символ препроцессора пустое значение или что-то еще. Просто
#define MY_CONDITION
или же
-DMY_CONDITION
достаточно, чтобы удовлетворить
#ifdef MY_CONDITION
развернуть текст, который идет позже (или скрыть его #ifndef
).
Compare
объявление не является символом препроцессора и не может быть разумно использовано с #ifdef
или же #ifndef
или.
#if
препроцессор if
, Он может иметь дело только с препроцессором, который в основном является макросами препроцессора (которые являются либо подобными функциям, либо постоянными), и токенами C с некоторой простой целочисленной литеральной арифметикой.
#ifdef SOMETHING
такой же как #if defined(SOMETHING)
а также#ifndef SOMETHING
такой же как #if !defined(SOMETHING)
, defined
это специальный оператор препроцессора, который позволяет вам проверить, является ли SOMETHING определенным макросом. В основном это ярлыки для наиболее распространенных применений или условных выражений препроцессора - проверки, определены ли некоторые макросы или нет.
Вы можете найти подробное руководство (~80 страниц) по препроцессору gcc по адресу https://gcc.gnu.org/onlinedocs/.
По сути, препроцессор выполняет подстановку текста. Затем компилятор компилирует программу в машинный код. И тогда процессор выполняет машинные инструкции. Это означает, что вы не можете использовать препроцессор #if
вместо оператора if
: один выполняет подстановку текста, а второй генерирует код ветвления для процессора.
Так директивы препроцессора, такие как #if
, #ifdef
, #ifndef
служат для "полуавтоматического режима" генерации (немного) разных программ на основе некоторого "мета-ввода". На самом деле вы всегда можете выполнить эти замены самостоятельно и получить работающую программу на C/C++ без каких-либо директив препроцессора. Кроме того, компиляторы часто имеют переключатель командной строки, который выводит только предварительно обработанную программу, т.е. #if
директивы. Попробуйте поиграть с ним, и вы должны понять, что делают эти директивы.
#ifdef XXX
это так же, как #if defined(XXX)
где defined(XXX)
встроенная функция только для препроцессора, которая имеет значение true, если идентификатор XXX определен в тексте программы другой директивой препроцессора #define
, А также #ifndef XXX
просто #if !defined(XXX)
,
Ну, препроцессоры #ifdef и #ifndef означают следующее: в вашем примере вы использовали #define, чтобы установить постоянную переменную с именем LINUX_GRAPHICS равной 011x101. Поэтому позже в вашей программе вы захотите проверить, определена ли эта переменная. Затем вы используете #ifdef, когда вы хотите проверить, определена ли эта переменная, и #ifndef, если нет. Хотел бы я помочь тебе.