Макросы C с использованием enum - PullRequest
0 голосов
/ 29 июня 2018

Я пытаюсь использовать макросы #if, определяя тип операции для вызова правильного кода, поэтому я сделал очень простой пример, аналогичный тому, что я пытаюсь сделать:

#include <stdio.h>

enum{ADD,SUB,MUL};

#define operation   ADD

int main()
{
   int a = 4;
   int b = 2;
   int c;

   #if (operation == ADD)
      c = a+b;
   #endif

   #if (operation == SUB)
      c = a-b;
   #endif

   #if (operation == MUL)
      c = a*b;
   #endif


   printf("result = %i",c);
   return 0;
}

Но, к сожалению, это не работает, я получаю следующее result = 8 ... если я заменю операцию с числами, она работает нормально .... Но я хочу, чтобы она работала, как описано выше.

Любая помощь

Ответы [ 4 ]

0 голосов
/ 29 июня 2018

Как уже говорили другие, препроцессор выполняет свои преобразования на очень ранней стадии компиляции, прежде чем станут известны значения enum. Так что вы не можете сделать этот тест в #if.

Однако вы можете просто использовать обычный оператор if. Любой достойный компилятор с включенной оптимизацией обнаружит, что вы сравниваете константы, выполняете тесты во время компиляции и выбрасывает код, который никогда не будет выполнен. Таким образом, вы получите тот же результат, которого пытались достичь с помощью #if.

0 голосов
/ 29 июня 2018

Препроцессор всегда будет считать это ложным:

#if IDENT == IDENT

Может проверять только числовые значения.

Упростите ваш код и передайте его препроцессору:

enum {ADD,SUB,MUL};

#define operation   ADD

int main()
{
    (operation == ADD);  
}

Результат вывода препроцессора:

enum {ADD,SUB,MUL};
int main()
{
    (ADD == ADD);    
}

Как видите, значение перечисления не было оценено. В выражении #if это выражение выглядит как false .

Так что обходным решением будет заменить ваше перечисление на серию #define:

#define ADD 1
#define SUB 2
#define MUL 3

вот так это работает. Выходной сигнал препроцессора теперь:

int main()
{
   int a = 4;
   int b = 2;
   int c;


      c = a+b;
# 28 "test.c"
   printf("result = %i",c);
   return 0;
}

решение:

  • либо полагаться на препроцессор на 100% (как предлагает решение выше)
  • или полностью полагаться на компилятор (используйте перечисления и действительные if операторы)
0 голосов
/ 29 июня 2018

Но я хочу, чтобы это работало так, как описано выше.

Вы, похоже, имеете в виду, что вы хотите, чтобы препроцессор распознал константы перечисления как таковые и оценивал выражения == в этом свете. Боюсь, тебе не повезло.

Препроцессор ничего не знает о перечислениях. Он работает с главным образом необработанным потоком токенов и пробелов. Когда он оценивает директиву, такую ​​как

#if (operation == SUB)

сначала выполняется расширение макроса для получения

#if (ADD == SUB)

. Затем он должен каким-то образом преобразовать токены ADD и SUB в числа, но, опять же, он ничего не знает о перечислениях или значении C предыдущего кода. Его правило для интерпретации таких символов как чисел простое: оно заменяет каждый на 0. В результате все три условия препроцессора в вашем коде всегда будут иметь значение true.

Если вы хотите, чтобы препроцессор делал это, вам нужно определить символы для препроцессора. Поскольку вы не используете enum иначе, вы можете просто заменить его на

#define ADD 1
#define SUB 2
#define MUL 3

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

0 голосов
/ 29 июня 2018

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

Вы просто не можете использовать условную компиляцию препроцессора с использованием перечислений.

...