В настоящее время я изучаю C, и я столкнулся с этим вопросом, на который не могу найти ответ.
Могу ли я выйти из #ifdef, не проходя через #endif?
Например, я могу сделать это:
char getOS( void ) {
/* Returns the user Operating System
*/
#ifdef _WIN32
return 'w';
#elif TARGET_OS_MAC
return 'm';
#elif __linux__
return 'l';
#else
raiseError( "You cannot play on this OS", true );
#endif
}
Что вы подразумеваете под "выпрыгнуть из"? В цепочке #if...#elif...#else
будет выбран только один.
cpp
условные операторы (например, #ifdef
, #elif
) не похожи на операторы C if
. Они не генерируют все возможности, как if
. Код #ifdef
«выбирает» на первом этапе компиляции. Итак, если _WIN32
определено, более поздние этапы компиляции будут видеть [только]: char getOS( void ) { return 'w'; }
и компилировать это. Вы можете заменить raiseError( "You cannot play on this OS", true );
на #error You cannot play on this OS
, чтобы компиляция не удалась, если вы компилируете в неподдерживаемой системе.
Я считаю, что вы немного неправильно понимаете препроцессор. Помните, препроцессор запускается перед компилятором. Таким образом, эта функция будет выглядеть примерно так, когда попадет в компилятор:
char getOS( void ) {
return 'w';
}
char getOS( void ) {
return 'm';
}
char getOS( void ) {
return 'l';
}
char getOS( void ) {
raiseError( "You cannot play on this OS", true );
}
... и все они действительны. Ну, я не знаю, что делает raiseError
, но если это не макрос, который return
s или exit
s, вам нужно будет добавить дополнительный return
в конец функции для ветки #else
.
Дело в том, что ни один из этих #if
, #elif
и т. д. все равно не попадет в компилятор, поэтому вы никогда не «выскакиваете». Если вы хотите убедиться сами, вы можете добавить параметр компилятора, чтобы выполнять только предварительную обработку (без компиляции). Я знаю, что для gcc
этот вариант -E
.
Большое тебе спасибо. Наконец-то я понимаю, что на самом деле делает препроцессор
Кажется, вы путаете препроцессор с поведением во время выполнения: это не одно и то же.
Препроцессор запускается до фактического компилятора (по крайней мере, концептуально; на практике, конечно, это может быть одна и та же программа). Это влияет на источник, который затем видит компилятор.
Вы не можете «пройти» #endif
, его нет, когда программа работает. У вас будет либо return
, либо звонок raiseError()
.
И тебе спасибо. Теперь я наконец понял :)
Если под «выпрыгнуть из» вы подразумеваете, что компилятор выдаст ошибку, вы можете сделать это с помощью директивы #error
.
#ifdef _WIN32
return 'w';
#elif TARGET_OS_MAC
return 'm';
#elif __linux__
return 'l';
#else
#error "You cannot play on this OS"
#endif
Под «выпрыгнуть из» я имел в виду, что если бы первое условие было истинным, я бы никогда не достиг #endif, и я подумал, что это может быть проблемой. Теперь я лучше понимаю, что на самом деле делает препроцессор. Ваше решение все еще полезно. Спасибо :)
Добавьте (например)
return 0;
послеraiseError
, чтобы все пути использовали возвратchar
. В противном случае ваш код в порядке.