История вопроса:
Оператор switch был введён в язык C для удобства распределения управления по нескольким веткам в зависимости от значения выражения. Это альтернатива большой цепочке if-else и широко применяется для обработки команд, состояний и значений перечислений.
Проблема:
Основные опасности оператора switch связаны с забытыми операторами break, неожиданным попаданием в "проваливание" (fallthrough), сложностями с переменными, объявленными внутри блока, а также с тем, что тип выражения должен быть целым.
Решение:
Для безопасного использования:
break (или явно отмечать необходимость fallthrough комментариями);int или совместимых с ним;case, обрабатывать в ветке default;case, либо в {}-области.Пример кода:
#include <stdio.h> void print_day(int day) { switch (day) { case 1: printf("Monday "); break; case 2: printf("Tuesday "); break; case 3: printf("Wednesday "); break; case 4: printf("Thursday "); break; case 5: printf("Friday "); break; case 6: case 7: printf("Weekend "); break; default: printf("Unknown day "); } }
Ключевые особенности:
Можно ли использовать тип float в выражении switch?
Нет. Стандарт языка C требует, чтобы выражение в switch было целочисленным или приведённым к целому (char, short, int, long, enum и т.д.).
Что произойдет, если переставить case'ы местами — влияет ли порядок на логику?
Порядок объявлений case в switch не влияет на поиск нужного значения. Код выполняется начиная с совпавшего case до первого break. Но порядок влияет при отсутствии break (fallthrough).
Можно ли объявлять переменные внутри case без фигурных скобок?
Нет. Если объявить переменную после case без дополнительного блока {} — это приведёт к ошибке компиляции. Корректно:
switch (x) { case 1: { int y = 0; break; } }
В большом проекте программист забыл break после одного из case и получил ошибочное выполнение нескольких веток подряд. Баг был замечен только пользователем.
Плюсы:
Минусы:
В случае, когда проваливание нужно, применялись комментированные fallthrough с пояснением, все критические case сопровождались break или return, в default выводилось предупреждение.
Плюсы:
Минусы: