Подтвердить что ты не робот

Почему метки в заявлении case должны быть постоянными?

В JavaScript действует следующий оператор.

switch(true) {
    case a > b:
        max = a;
        break;
    case a < b:
        max = b;
        break;
    default:
       max = a;
}

Но на языках программирования C/С++, когда я пишу этот оператор, компилятор дает мне ошибку, показывающую, что оператор case должен состоять из постоянных значений. Иногда в особых случаях писать такие сообщения switch-case было бы очень полезно, но C/С++ не позволит мне это сделать.

Теперь мне любопытно узнать, в чем смысл этого, чтобы не использовать значения переменных в утверждениях case?

4b9b3361

Ответ 1

С++ развился с C, где операторы switch были задуманы как Таблица переходов (таблица веток). Чтобы реализовать в качестве таблиц перехода, условия переключения должны быть постоянными, чтобы их можно было легко перевести на метку.

Хотя стандарт никогда не диктует, как должны выполняться инструкции switch, но, что наиболее важно, метки case должны быть такими, чтобы их можно было оценить во время компиляции. В C и С++ оператор switch оценивает выражение и передает управление одному из многих значений case case, который вычисляет значение условного выражения.

6.4.2 Оператор switch [stmt.switch]

Оператор switch приводит к тому, что управление передается одному из нескольких операторов в зависимости от значения условия.

Такое поведение отличает его от других языков, поддерживающих условия в заявлениях о случаях.

Что касается экземпляра, Javascript описывает оператор switch ... case как

MDN-переключатель

Оператор switch вычисляет выражение, сопоставляя значение выражения с предложением case и выполняет инструкции, связанные с этим случаем.

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

Что касается ответа the point behind this to not allowing variable values to be used in case statements?, это сделало бы switch .. case менее эффективной конструкцией, где для каждой итерации/экземпляра метки case должны быть переоценены, чтобы определить, соответствует ли это условному выражению.

Ответ 2

Стандарт C (а не С++) гласит:

C11: 6.8.4.2 Оператор switch (p3)

Выражение каждой метки case должно быть целочисленным константным выражением, а никакие два из константных выражений case в одном и том же выражении switch не должны иметь то же значение после преобразования. [...]

Если выражения были разрешены в case, тогда есть возможности, что два выражения могут иметь одинаковое значение.

Стандарт С++ (а не C) говорит то же самое:

С++ 11: 6.4.2 пункт 2:

[...] Ни одна из констант case в том же коммутаторе не должна иметь одинаковое значение после преобразования в продвинутый тип условия переключения.

Ответ 3

Причина существования switch/case (с учетом того, что if/else существует для всего остального) заключается в предоставлении аналога для синтаксиса "jump" более низкого уровня, чтобы вы могли создавать быстрый, статический "таблицы перехода" для вашего кода. Эта причина испаряется, если вы разрешаете выражения времени выполнения.

Спрашивая, почему switch эта вещь сродни спросу, почему if делает другую вещь и поэтому пуст.

Ответ 4

Просто потому, что вы можете что-то сделать, это не значит, что это имеет смысл. В частности, switch не эквивалентен лестницам if/else.

if/else более общий, чем switch, который предназначен для "выбора того, что нужно делать на основе значения выражения switch".

Упражнение - что сделал бы следующий код?

var a = 5;
var b = 0;
switch(a)
{
    case 5: b = 1; break;
    case 5: b = 2; break;
    case 1: b = 3; break;
}

Теперь b равно 2 или 1? Если он выполняет обе ветки, он не делает "выбрать одну вещь, чтобы сделать", если она делает одно, а не другое, это произвольное решение.

Ограничение значений case, которые являются константными выражениями, позволяет компилятору выдавать ошибку в этом коде. Если значения могут отличаться в зависимости от значения во время выполнения, компилятор не сможет проверить, что два случая имеют одинаковые значения, как следствие проблемы с остановкой.