#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, если нет. Хотел бы я помочь тебе.

Другие вопросы по тегам