Почему я не могу сравнить макрос и перечисление, используя #if? - PullRequest
3 голосов
/ 10 июня 2019

Я пытаюсь проверить с помощью #if, что макрос и перечисление равны или нет. проверка не проходит, даже если оба имеют одинаковое значение. почему?

Создан макрос с использованием #define NUMBER 2. Создан enum, включающий одну запись со значением 2. Сравнил оба с использованием #if. сравниваемый макрос со значением 2 передается. но сравнивать макрос с enum не удается.

#include <stdio.h>
#define NUMBER 2
enum numbers
{
    zero = 0, 
    one, 
    two, 
    three
};

int main ()
{
    printf("NUMBER: %x and two: %x\n", NUMBER, two);

#if NUMBER == two
    printf("#1-------PASS\n");
#else
    printf("#1--------FAIL\n");
#endif

#if NUMBER == 2
    printf("#2-------PASS\n");
#else
    printf("#2--------FAIL\n");
#endif

    if (NUMBER == two)
        printf("#3-------PASS\n");
    else
        printf("#3--------FAIL\n");
}

Я ожидал PASS для всех трех случаев. Фактический результат:

NUMBER: 2 and two: 2
#1--------FAIL
#2-------PASS
#3-------PASS

1 Ответ

5 голосов
/ 10 июня 2019

Обработка #if и макросов выполняется на ранних этапах перевода программы на Си. То есть это делается во время "предварительной обработки". На этих этапах не существует понятия счетчиков (которые обрабатываются намного позже). Препроцессор работает только с токенами, и замена одного токена на ноль или более других токенов - это все, что он действительно может сделать на этом этапе. Перечисление - это семантическая конструкция, больше, чем просто суп из токенов, поэтому препроцессор опять ничего об этом не знает.

Когда вы используете two, препроцессор будет обрабатывать его как токен предварительной обработки, так же как он обрабатывает NUMBER. Это попытается заменить это, чтобы произвести некоторое допустимое условие. Но это был не #define d, поэтому он использует резервное поведение. Каждый токен, который не определен, но используется в #if, заменяется на 0. В результате проверяется условие:

#if 2 == 0
...