Сценарий провала Switch Case

Итак, я столкнулся с конкурентным вопросом (запрашивая результат) следующим образом:

#include <stdio.h>
int main()
{
    int i = 0;
    for(i = 0; i < 20; i++)
    {
        switch(i)
        {
            case 0: i+=5;
            case 1: i+=2;
            case 5: i+=5;
            default: i+= 4;
            break;
        }
        printf("%d ", i);
    }
    return 0;
}

Выход 16, 21. Хотя я знаю, как работает регистр переключения, я не могу объяснить себе, как работает этот провал. Почему добавляется значение по умолчанию? Разве в книге K&R C не сказано, что значение по умолчанию выполняется только в том случае, если ни один из случаев не совпадает?
Спасибо.


person Jishan    schedule 30.08.2014    source источник
comment
Нет, провал происходит независимо от того, является ли следующий случай default или нет.   -  person chris    schedule 30.08.2014
comment
Вы не выполняете дефолт, вы выполняете какой-то случай выше, который проваливается в дефолт.   -  person Mohit Jain    schedule 30.08.2014
comment
Не уверен, для чего здесь минус, это вполне разумный способ прочитать раздел K&R, на который ссылается ОП, для новичка. Случай, помеченный как default, выполняется, если ни один из других случаев не удовлетворяется, звучит точно так, как он ожидал.   -  person Patrick Collins    schedule 30.08.2014
comment
Почему он добавляет 2 в случае 1?   -  person psrag anvesh    schedule 20.01.2016


Ответы (4)


Случай по умолчанию переходит к из инструкции switch только в том случае, если нет других подходящих случаев. После того, как один из них совпал, код выполняется так, как если бы не существовало ни одного из операторов case, пока не встретится break. Таким образом, случай default не "перепрыгнул", как вы ожидаете.

K & R немного неясно об этом, строка, на которую вы ссылаетесь, кажется:

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

Но это говорит о том, как оператор switch ветвится. Поведение Fallthrough описано на следующей странице:

Поскольку кейсы служат просто метками, после выполнения кода для одного кейса выполнение переходит к следующему, если только вы не предпримете явных действий для выхода.

что не зависит от того, есть ли случай default.

Стандарт C понятнее:

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

После перехода управления метки case и default больше не имеют значения.

person Patrick Collins    schedule 30.08.2014
comment
Точно, я запутался в этой строке. Спасибо за объяснение, теперь мне все ясно. - person Jishan; 30.08.2014

«Тело» оператора switch представляет собой один непрерывный линейный составной оператор. Метки case — это просто метки, которые определяют разные точки входа в этот непрерывный оператор. Метка default тоже просто метка, ничем не отличающаяся от меток case в этом отношении.

Как только вы вошли в составной оператор switch через метку, выполнение продолжится в обычном режиме: последовательно до конца составного оператора (на этом этапе метки case/default уже не играют никакой роли). Если вы хотите, чтобы этого не произошло, вы обязаны в подходящий момент выпрыгнуть из этого составного утверждения. Вы можете использовать для этого любой оператор перехода, имея в виду, что в вашем распоряжении также есть break (что в большинстве случаев является наиболее подходящим выбором).

Другими словами, switch не является сильно структурированным селектором ветвей, как может показаться на первый взгляд. switch — это просто слегка структурированный многоцелевой goto. Все, что он делает, это один параметризованный переход во время выполнения. Все, что после этого прыжка, — ваша ответственность.

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

person AnT    schedule 30.08.2014

В случаях переключения нет «разрыва», кроме значения по умолчанию.

Когда оператор switch используется без разрывов, код продолжает выполняться даже после того, как найден соответствующий случай.

Пожалуйста, смотрите ниже исправленный код:

    switch(i)
    {
        case 0: i+=5;
        break;
        case 1: i+=2;
        break;
        case 5: i+=5;
        break;
        default: i+= 4;
        break;
    }
person Pavi    schedule 30.08.2014

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

person Nizamuddin Shaikh    schedule 30.08.2014