Оператор switch case в языке C — это конструкция выбора, которая сравнивает значение одного целочисленного выражения с набором констант и выполняет ту ветку case, чья константа совпала. Он заменяет длинную цепочку if / else if, когда решение зависит от одного значения: номера пункта меню, кода дня недели, символа-оценки.
Содержание
Ниже — синтаксис switch, роль ключевого слова break, что такое проваливание (fallthrough) без break, зачем нужна ветка default и какие типы данных допустимы. Все примеры — полные программы на C, которые можно скомпилировать и запустить; вывод в тексте сверен с реальным.
Синтаксис оператора switch case
Общий вид конструкции такой:
switch (выражение) {
case константа_1:
операторы;
break;
case константа_2:
операторы;
break;
default:
операторы;
}
Работает это так: вычисляется выражение в скобках, затем его значение по очереди сравнивается с константами в case. При первом совпадении управление переходит внутрь этого case, и операторы выполняются до break. Ветка default срабатывает, если не совпал ни один case.
Вот минимальная полная программа — вывод названия дня недели по его номеру:
#include <stdio.h>
int main(void) {
int day = 3;
switch (day) {
case 1:
printf("Понедельник\n");
break;
case 2:
printf("Вторник\n");
break;
case 3:
printf("Среда\n");
break;
default:
printf("Такого дня недели нет\n");
}
return 0;
}
Для day = 3 совпадает третий case, и в консоли появится:
Среда
Чтобы читать значение с клавиатуры, замените присваивание на ввод: scanf("%d", &day); (символ & обязателен — scanf нужен адрес переменной).
Оператор break и проваливание (fallthrough)
break выходит из switch сразу после выполненной ветки. Если его убрать, начинается проваливание (fallthrough): выполнение не останавливается на границе case, а продолжается в следующий case и дальше — до break или до конца switch. Метки case тут работают только как точки входа, а не как отдельные блоки.
Это частый источник ошибок. Возьмем ту же программу, но уберем все break:
#include <stdio.h>
int main(void) {
int day = 2;
switch (day) {
case 1:
printf("Понедельник\n");
case 2:
printf("Вторник\n");
case 3:
printf("Среда\n");
default:
printf("Такого дня недели нет\n");
}
return 0;
}
Ожидался бы один «Вторник», но фактический вывод для day = 2 такой:
Вторник
Среда
Такого дня недели нет
Управление вошло в case 2 и, не встретив break, провалилось в case 3 и default. Исправление — вернуть break в конце каждой ветки:
#include <stdio.h>
int main(void) {
int day = 2;
switch (day) {
case 1:
printf("Понедельник\n");
break;
case 2:
printf("Вторник\n");
break;
case 3:
printf("Среда\n");
break;
default:
printf("Такого дня недели нет\n");
}
return 0;
}
Теперь вывод ровно один:
Вторник
Правило простое: если ветки не должны сливаться, каждая заканчивается break (последнюю ветку тоже стоит закрывать break — чтобы при добавлении нового case ниже ничего не провалилось).
Осознанное проваливание: несколько case на одно тело
У проваливания есть и полезное применение. Если несколько значений должны привести к одному действию, метки case ставят подряд, без операторов и без break между ними — тело пишут после последней метки группы:
#include <stdio.h>
int main(void) {
char grade = 'B';
switch (grade) {
case 'A':
case 'B':
case 'C':
printf("Зачет сдан\n");
break;
case 'D':
case 'F':
printf("Нужна пересдача\n");
break;
default:
printf("Неизвестная оценка\n");
}
return 0;
}
Символ 'B' попадает в группу A/B/C, поэтому вывод:
Зачет сдан
Здесь switch работает по символу: в C тип char — это целое число (код символа), поэтому в case можно писать символьные константы вроде 'A'. Это допустимая и распространенная форма, а не обход правил.
Ветка default: когда совпадений нет
default — это ветка «во всех остальных случаях». Она не обязательна: если ее нет и ни один case не совпал, switch просто ничего не делает. Но для надежного кода default полезен — он ловит неучтенные значения.
#include <stdio.h>
int main(void) {
int choice = 9;
switch (choice) {
case 1:
printf("Открыть файл\n");
break;
case 2:
printf("Сохранить файл\n");
break;
default:
printf("Нет такого пункта меню\n");
}
return 0;
}
Значение 9 не совпало ни с одним case, сработала ветка по умолчанию:
Нет такого пункта меню
Формально default можно разместить не только в конце, но и между case — на порядок проверки это не влияет (сравнение всегда идет по case, а default рассматривается последним). Но по договоренности его пишут в конце: так код читается привычнее.
Какие типы и значения допустимы
На switch в C есть жесткие ограничения — о них стоит знать заранее, иначе программа не скомпилируется.
- Выражение в
switchдолжно быть целочисленного типа:int,char,enum, другие целые. Дробныеfloatиdoubleнедопустимы. - Метки
case— только константные целочисленные выражения (число, символьная константа, элементenum). Переменную или диапазон видаcase 1..5в стандартном C поставить нельзя. - Константы всех
caseв одномswitchдолжны быть уникальны.
Например, switch по double не соберется:
double x = 2.0;
switch (x) { // так нельзя: тип double недопустим
case 2:
printf("два\n");
break;
}
Компилятор остановится с ошибкой. Точный текст зависит от инструментов: Apple clang сообщает statement requires expression of integer type ('double' invalid), GCC — switch quantity not an integer. Смысл один: в switch нужно целое.
Такая же ошибка компиляции будет при двух одинаковых case (например, два case 1 подряд): clang пишет duplicate case value, GCC — похоже. Это удобно — опечатка ловится сразу, а не в рантайме.
switch или if…else: что выбрать
switch и цепочка if / else if решают одну задачу — ветвление, но подходят под разные ситуации.
| Задача | Что взять | Почему |
|---|---|---|
| Сравнить одну переменную с набором конкретных значений | switch | читается как таблица вариантов, компактнее длинной цепочки else if |
Диапазоны и неравенства (x > 100, 0 < x < 10) |
if…else | switch сравнивает только на равенство с константами |
Дробные числа (double, float) |
if…else | switch не принимает нецелые типы |
| Сравнение строк | if…else со strcmp |
switch не умеет сравнивать строки в C |
| Много веток по одному целому значению | switch | нагляднее и обычно быстрее читается |
Проще говоря: один целый ключ и точные значения — switch; диапазоны, дроби, строки или сложные условия — if...else.
Выводы
switch caseв языке C выбирает ветку по значению одного целочисленного выражения и заменяет длинную цепочкуif / else if, когда решение зависит от одного значения.breakзавершаетswitch; без него начинается проваливание — выполнение продолжается в следующиеcase(в примере вышеday = 2безbreakдал три строки вместо одной).- Проваливание можно применять осознанно: несколько меток
caseподряд безbreakнаправляют разные значения в одно тело. defaultсрабатывает, когда не совпал ни одинcase; ветка не обязательна, но защищает от неучтенных значений.- В
switchдопустимы только целые типы (int,char,enum), меткиcase— уникальные целочисленные константы;double, диапазоны и строки — это территорияif...else.
Где применяется на практике
Оператор switch case — базовый инструмент управления потоком в C и близких языках: разбор пунктов меню, обработка кодов команд и состояний, диспетчеризация по типу события, интерпретаторы и конечные автоматы. Умение видеть, где switch читается лучше цепочки условий, — часть культуры чистого кода на C.
Освойте тему на практике
Освоить синтаксис C системно, с практикой и обратной связью от преподавателей, помогает курс Программирование на C++ с нуля: C и C++ разделяют общее процедурное ядро, включая switch case, break и default, с которого начинают оба языка.
Освойте тему на практике
Посмотреть, как разбирают такие конструкции вживую, и задать вопросы можно на открытых вебинарах Otus — они бесплатные и проходят регулярно.
Смежные темы: Переменные в языке C, Оператор return в C, Циклы в программировании.
FAQ
Обязательно ли ставить break в последней ветке switch? Программа отработает и без него, но break (или break после default) стоит ставить всегда: как только ниже добавят новый case, забытый break приведет к незаметному проваливанию.
Можно ли в case указать диапазон значений, например от 1 до 10? В стандартном C — нет, метка case принимает только одну константу. Для диапазона перечислите значения отдельными метками case подряд или используйте if...else.
Что быстрее — switch или if…else? Для сравнения одного целого с набором констант компилятор часто превращает switch в таблицу переходов, и он может быть быстрее длинной цепочки if. Но разница обычно несущественна; выбирают по читаемости, а не по скорости.



