Работа условной компиляции #if и #else (и других) в c - PullRequest
0 голосов
/ 02 февраля 2019

Я попытался написать программу, используя некоторые директивы предварительной обработки условной компиляции вместо «if-else», как показано ниже.

#include<stdio.h>
int main ()
{
    int x;
    scanf ("%d",&x);
#if (x==5)
    printf ("x is 5");
#else
    printf ("x not 5");
#endif
}

Но дело в том, что она всегда печатает часть else, даже если значениеx равно 5.Мой самый простой вопрос: -----> ПОЧЕМУ?

Возможно ли успешно завершить эту программу (т.е. получить значение x от пользователя и проверить условия с помощью директивы #if и оператора printпод #if).

Во время компиляции выдается предупреждение "x" не определено, равно 0 ".Но x кажется мне определенным.Означает ли это, что x должно быть определено с помощью #define.Пожалуйста, объясните мне концепцию условной компиляции.

Ответы [ 4 ]

0 голосов
/ 03 февраля 2019

Операндами в операторах #if могут быть только константы, вещи, определенные с помощью #define, и специальный оператор defined.Любые другие идентификаторы в выражении заменяются на 0. x в вашем примере кода не определено с #define, поэтому (x==5) становится (0==0).

В стандарте C 2018, п. 6.10.1 говорит нам, что оценка выражения в операторе #if включает:

  • Макросы препроцессора (вещи, определенные с помощью #define) заменяются в соответствии с их определениями.
  • Используетоператора defined заменяются на 0 или 1.
  • Все остальные идентификаторы заменяются на 0.

, поскольку x в вашем примере кода не определено с помощью #define, он заменяется на 0 в выражении #if.В результате получается (0==5), что неверно, поэтому код между #if и #else пропускается.

В операторе препроцессора нельзя вычислять переменные на основе значений, которые будут установлены во время программывыполнение.

0 голосов
/ 02 февраля 2019

Предварительная обработка происходит до компиляции.Так что препроцессор ничего не знает о вашем C-коде или переменных.В условиях нельзя использовать любые переменные C.

Условная компиляция для разных целей.

#define DEBUG

/* ....*/ 

#ifdef DEBUG 
printf("Some debug value %d\n", val);
#endif
0 голосов
/ 02 февраля 2019

x не является целочисленным литералом или целочисленным литеральным выражением (целочисленные литералы + операторы) или макросом, расширяющимся до них, поэтому в условном выражении препроцессор заменяет его на 0 ( 6.10.1p4 ).0==5 имеет значение false, поэтому берется ветвь #else.

Препроцессор не знает о объявлениях, типах C и подобных.Он работает только с токенами (и макросами, которые в конечном итоге расширяются до этих).


6.10.1p4

После всех замен из-за расширения макроса иопределенный унарный оператор был выполнен, все оставшиеся идентификаторы (включая лексически идентичные ключевым словам) заменены на номер pp 0, а затем каждый токен предварительной обработки преобразуется в токен.

0 голосов
/ 02 февраля 2019

Это «препроцессор».«Pre» означает «до».

Вы пытаетесь использовать значение runtime во время предварительной обработки!Конечно, препроцессор не имеет доступа к этой информации во время сборки.

Эта проблема не ограничивается значениями времени выполнения, но является более фундаментальной.Даже если вы пытаетесь использовать (именованную) константу времени компиляции, такую ​​как constexpr int x = 2, вы не сможете этого сделать.Это два языка чередования, такие как генерация HTML с PHP;HTML не знает переменных PHP, а PHP не знает, какие виджеты пользователь нажимает на странице.Это совершенно разные контексты выполнения без встроенного взаимодействия или перекрестной совместимости.

...