Как стать автором
Обновить

Забавы с оператором switch

Время на прочтение2 мин
Количество просмотров1.4K
Был у меня простой, рабочий код (я убрал лишнее оставил только суть):
typedef enum
  {
    enNone,
    enOne,
    enTwo,
    enThree
  }TEnum;

    switch(Enum)
      {
        case enNone:
             /*Ничего не делаем*/
             break;/*enNone*/
        case enOne:
             Value=f1(Value);
             Value=A*Value+B;
             break;/*enOne*/
        case enTwo:
             Value=f2(Value);
             Value=A*Value+B;
             break;/*enTwo*/
        case enThree:
             Value=f3(Value);
             Value=A*Value+B;
             break;/*enThree*/
      }/*SWITCH*/


Больших претензий к нему у меня не было, но решил его микрооптимизировать:

Решил устранить избыточность и вынести отдельно общее преобразование.
Получилось так:
    if(enNone!=Enum)
      {
        switch(Enum)
          {
            case enOne:
                 Value=f1(Value);
                 break;/*enOne*/
            case enTwo:
                 Value=f2(Value);
                 break;/*enTwo*/
            case enThree:
                 Value=f3(Value);
                 break;/*enThree*/
          }/*SWITCH*/
        Value=A*Value+B;
      }/*THEN*/


Всё замечательно: код стал компактней, правильность кода не ухудшилась, но компилятор стал выдавать предупреждение, что в операторе switch одна из констант перечисления не обрабатывается.

Я стараюсь программировать так, чтобы не было warning'ов, потому задумался, а что здесь можно сделать, и вспомнив устройство Даффа, сделал так:

    switch(Enum)
      {
        case enNone: break;
        do
          {
            case enOne:
                 Value=f1(Value);
                 break;/*enOne*/
            case enTwo:
                 Value=f2(Value);
                 break;/*enTwo*/
            case enThree:
                 Value=f3(Value);
                 break;/*enThree*/
          }while( 0 );
        Value=A*Value+B;
      }/*SWITCH*/


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

Этот код работает только потому, что в языке Си для оператора switch ограничения на составной оператор ослаблены настолько, что требуется только чтобы он был правильно составлен и метки case: стояли перед операторами.
Только первый оператор break; выходит из конструкции switch, остальные выходят из цикла do {} while.

Ещё я знаю, что такую особенность switch используют для организации сопроцессов в Си, но, к сожалению, пример такого полезного применения этой особенности не удалось найти.
Теги:
Хабы:
Всего голосов 13: ↑5 и ↓8-3
Комментарии9

Публикации