Переключение операторов в C: переменная в случае? - PullRequest
8 голосов
/ 13 августа 2011
#include <stdio.h>
int main(int argc, char *argv[]){
    char a = 'c';
    switch('c'){
        case a:
            printf("hi\n");
    }
    return 0;
}

Выше не скомпилируется для этой ошибки:

case label does not reduce to an integer constant

Почему это не разрешено?

Ответы [ 4 ]

5 голосов
/ 13 августа 2011

Компилятору явно разрешено использовать эффективное двоичное дерево или таблицу переходов для оценки операторов case.

По этой причине операторы case являются константами времени компиляции.

5 голосов
/ 13 августа 2011

Подумайте, что если бы у вас было следующее:

int a = 1, b = 1, c = 1;

switch (a)
{
case b: return 1;
case c: return 2;
}

Что бы это вернуло?

Метки регистра должны быть постоянными, чтобы компилятор мог доказать, что нетнеясности.

3 голосов
/ 13 августа 2011

Идея оператора switch состоит в том, что компилятор может создавать код, который проверяет только выражение switch во время выполнения и тем самым определяет местоположение, к которому нужно перейти.

Если метка case может быть выражением, которое не является константой, она должна будет оценить все такие выражения case, чтобы увидеть, существует ли такое, которое соответствует. Таким образом, вместо оценки одного выражения, он должен будет оценить n выражений, где n - это число case меток для этого switch.

Вся идея switch состоит в том, чтобы сделать это наоборот, чем вы. Поместите переменное выражение a в сам switch и поместите константы, такие как 'c' в регистр.

2 голосов
/ 13 августа 2011

Стандарт C99 говорит об этом (и стандарт C89 был очень похож):

§6.8.4.2 Оператор switch

Препятствия

¶1 Управляющее выражение оператора switch должно иметь целочисленный тип.

[...]

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

Это требование языка: метки регистра должны быть целочисленными константами, и все регистры в одном переключателе должны быть уникальными. Именно так был разработан С. Сейчас маловероятно, что оно изменится (даже если изменение не нарушит действующий на данный момент код и даже не изменит его значение).

...