Re: семантика switch/case
От: maxluzin Европа  
Дата: 30.12.15 07:38
Оценка:
Здравствуйте, _hum_, Вы писали:

__>Всегда полагал, что семантика switch/case/case/... аналогична if/if/if/... без break-а и if/else if/else if/... c break-ом. А тут решил не ставить break "в конце ветки выбора", и опля — сюрприз. Так что, товарищи, кто еще так же, как и я, заблуждался, будьте внимательны:

// ...
__>p.s. Вопрос к знатокам — зачем такая неочевидная и "техническая" семантика?

В известной книжке отцов-основателей языка "С" Кернигана и Ритчи в главе 3.4 приводится такой пример:
#include <stdio.h>
main() /* подсчет цифр, символов-разделителей и прочих символов */
{
    int c, i, nwhite, nother, ndigit[10];
    nwhite = nother = 0;
    for (i = 0; i < 10; i++)
        ndigit[i] = 0;
    while ((с = getchar()) != EOF) {
        switch (c) {
        case '0' : case '1' : case '2' : case '3' : case '4' :
        case '5' : case '6' : case '7' : case '8' : case '9' :
            ndigit[c - '0']++;
            break;
        case ' ':
        case '\n':
        case '\t':
            nwhite++;
            break;
        default:
            nother++;
            break;
        }
    }
    printf ("цифр =");
    for (i = 0; i < 10; i++)
        printf (" %d", ndigit[i]);
    printf(", символов-разделителей = %d, прочих = %d\n",
            nwhite, nother);
    return 0;
}

...как альтернатива той же самой программы, но с использованием if...then в первой главе:

#include <stdio.h>

/* подсчет цифр, символов-разделителей и прочих символов */
main()
{
    int с, i, nwhite, nother;
    int ndigit[10];

    nwhite = nother = 0;
    for (i = 0; i < 10, ++i)
        ndigit[i]= 0;
    while ((c = getchar()) != EOF)
        if (c >='0' && с <= '9')
            ++ndigit[c – '0'];
        else if (c == ' ' || c == '\n' || c == '\t')
            ++nwhite;
        else 
            ++nother;

    printf(“цифры =“);
    for (i = 0; i < 10; ++i)
        printf(“%d”, ndigit[i]);
    printf(“, символы-разделители =%d, прочие =%d\n”, nwhite, nother);
}


Там же они сами и дают комментарий на этот счёт:

"Сквозное" выполнение ветвей case вызывает смешанные чувства. С одной стороны, это хорошо, поскольку позволяет несколько ветвей case объединить в одну, как мы и поступили с цифрами в нашем примере. Но с другой — это означает, что в конце почти каждой ветви придется ставить break, чтобы избежать перехода к следующей. Последовательный проход по ветвям — вещь ненадежная, это чревато ошибками, особенно при изменении программы. За исключением случая с несколькими метками для одного вычисления, старайтесь по возможности реже пользоваться сквозным проходом, но если уж вы его применяете, обязательно комментируйте эти особые места.

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


Где-то в другом месте в интервью (которое я уже не найду) они сказали про switch...case, что так было проще и естественнее реализовывать компилятор с "С" на скудных ресурсах PDP-11 (кажется), т.к. компилятор с "С" является однопроходным и это тогда выставлялось его огромным преимуществом, т.к. программы компилировались значительно быстрее, чем на двух-проходных... Отмазка, короче...
Отредактировано 30.12.2015 8:00 maxluzin . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.