Введение
Тип механизма управления выбором в языках программирования.
In computer programming languages, a switch statement is a type of selection control mechanism used to allow the value of a variable or expression to change the control flow of program execution via search and map. Switch statements function somewhat similarly to the if statement used in programming languages like C/C++, C#, Visual Basic NET, Java and exist in most high level imperative programming languages such as Pascal, Ada, C/C++, C#, Visual Basic NET, Java, and in many other types of language, using such keywords as switch, case, select or inspect. Switch statements come in two main variants: a structured switch, as in Pascal, which takes exactly one branch, and an unstructured switch, as in C, which functions as a type of goto. The main reasons for using a switch include improving clarity, by reducing otherwise repetitive coding, and (if the heuristics permit) also offering the potential for faster execution through easier compiler optimization in many cases. +Switch statement in Cswitch (age) {
case 1: printf("You're one. "); break;
case 2: printf("You're two. "); break;
case 3: printf("You're three. "); break;
case 4: printf("You're three or four. "); break;
default: printf("You're not 1, 2, 3 or 4! ");
}
В языках программирования оператор `switch` является типом механизма управления выбором, используемым для изменения потока выполнения программы в зависимости от значения переменной или выражения посредством поиска и сопоставления. Операторы `switch` функционируют аналогично оператору `if`, используемому в языках программирования, таких как C/C++, C#, Visual Basic NET, Java, и существуют в большинстве императивных языков программирования высокого уровня, таких как Pascal, Ada, C/C++, C#, Visual Basic NET, Java, и во многих других языках, используя ключевые слова `switch`, `case`, `select` или `inspect`. Операторы `switch` бывают двух основных видов: структурированный `switch`, как в Pascal, который выполняет ровно одну ветвь, и неструктурированный `switch`, как в C, который функционирует как разновидность оператора `goto`. Основные причины использования `switch` включают повышение ясности кода за счет уменьшения повторяющихся конструкций и (если это позволяет оптимизация компилятора) потенциальное ускорение выполнения программы во многих случаях. +Оператор `switch` в C:
In computer programming languages, a switch statement is a type of selection control mechanism used to allow the value of a variable or expression to change the control flow of program execution via search and map. Switch statements function somewhat similarly to the if statement used in programming languages like C/C++, C#, Visual Basic NET, Java and exist in most high level imperative programming languages such as Pascal, Ada, C/C++, C#, Visual Basic NET, Java, and in many other types of language, using such keywords as switch, case, select or inspect. Switch statements come in two main variants: a structured switch, as in Pascal, which takes exactly one branch, and an unstructured switch, as in C, which functions as a type of goto. The main reasons for using a switch include improving clarity, by reducing otherwise repetitive coding, and (if the heuristics permit) also offering the potential for faster execution through easier compiler optimization in many cases. +Switch statement in Cswitch (age) {
case 1: printf("You're one. "); break;
case 2: printf("You're two. "); break;
case 3: printf("You're three. "); break;
case 4: printf("You're three or four. "); break;
default: printf("You're not 1, 2, 3 or 4! ");
}
```c
switch (age) {
case 1: printf("Вам один год. "); break;
case 2: printf("Вам два года. "); break;
case 3: printf("Вам три года. "); break;
case 4: printf("Вам три или четыре года. "); break;
default: printf("Вам не 1, 2, 3 или 4 года! ");
}
```
In computer programming languages, a switch statement is a type of selection control mechanism used to allow the value of a variable or expression to change the control flow of program execution via search and map. Switch statements function somewhat similarly to the if statement used in programming languages like C/C++, C#, Visual Basic NET, Java and exist in most high level imperative programming languages such as Pascal, Ada, C/C++, C#, Visual Basic NET, Java, and in many other types of language, using such keywords as switch, case, select or inspect. Switch statements come in two main variants: a structured switch, as in Pascal, which takes exactly one branch, and an unstructured switch, as in C, which functions as a type of goto. The main reasons for using a switch include improving clarity, by reducing otherwise repetitive coding, and (if the heuristics permit) also offering the potential for faster execution through easier compiler optimization in many cases. +Switch statement in Cswitch (age) {
case 1: printf("You're one. "); break;
case 2: printf("You're two. "); break;
case 3: printf("You're three. "); break;
case 4: printf("You're three or four. "); break;
default: printf("You're not 1, 2, 3 or 4! ");
}
Семантика
Семантически существуют две основные формы операторов switch. Первая форма – это структурированные операторы switch, как в Паскале, где выполняется ровно одна ветвь, а case-ы рассматриваются как отдельные, взаимоисключающие блоки. Это функционирует как обобщенное условное выражение if–then–else, здесь с любым количеством ветвей, а не только с двумя. Вторая форма – неструктурированные операторы switch, как в C, где case-ы рассматриваются как метки внутри единого блока, а оператор switch функционирует как обобщенный переход goto. Это различие называется обработкой "fallthrough", которое рассматривается подробнее ниже.
Проникновение
Во многих языках выполняется только соответствующий блок, а затем выполнение продолжается в конце оператора `switch`. К ним относятся семейство языков Pascal (Object Pascal, Modula, Oberon, Ada и т. д.), а также PL/I, современные версии Fortran и диалекты BASIC, испытавшие влияние Pascal, большинство функциональных языков и многие другие. Чтобы позволить нескольким значениям выполнять один и тот же код (и избежать дублирования кода), языки, подобные Pascal, допускают любое количество значений для каждого `case`, задаваемых в виде списка, разделенного запятыми, в виде диапазона или их комбинации. Языки, произошедшие от языка C, и в более общем смысле те, на которые повлиял вычисляемый `GOTO` в Fortran, вместо этого реализуют "проскакивание" (fallthrough), когда управление передается в соответствующий `case`, а затем выполнение продолжается ("проскакивает") к операторам, связанным со следующим `case` в исходном тексте. Это также позволяет нескольким значениям соответствовать одной и той же точке без какого-либо специального синтаксиса: они просто перечисляются с пустыми телами. Значения могут быть дополнительно обусловлены кодом внутри тела `case`. На практике проскакивание обычно предотвращается с помощью ключевого слова `break` в конце соответствующего тела, которое завершает выполнение блока `switch`, но это может приводить к ошибкам из-за непреднамеренного проскакивания, если программист забудет вставить оператор `break`. Поэтому многие считают это недостатком языка и предупреждают об этом в некоторых инструментах статического анализа кода. Синтаксически, `case` интерпретируются как метки, а не блоки, и операторы `switch` и `break` явно изменяют поток управления. Некоторые языки, испытавшие влияние C, такие как JavaScript, сохраняют проскакивание по умолчанию, в то время как другие удаляют его или разрешают только в особых случаях. Заметные вариации в семействе C включают C#, в котором все блоки должны быть завершены оператором `break` или `return`, если только блок не пуст (то есть проскакивание используется для указания нескольких значений). В некоторых случаях языки предоставляют возможность опционального проскакивания. Например, Perl не проскакивает по умолчанию, но `case` может явно разрешить это с помощью ключевого слова `continue`. Это предотвращает непреднамеренное проскакивание, но позволяет его использовать при необходимости. Аналогично, Bash по умолчанию не проскакивает при завершении оператором `;;`, но разрешает проскакивание с помощью `;&` или `;&&` вместо этого. Примером оператора `switch`, который полагается на проскакивание, является устройство Даффа.
Сборник
Оптимизирующие компиляторы, такие как GCC или Clang, могут компилировать оператор `switch` либо в таблицу переходов, либо выполнять двоичный поиск по значениям в блоках `case`. Таблица переходов позволяет оператору `switch` определить, какую ветвь выполнять, с помощью небольшого, постоянного числа инструкций, не проходя через последовательность сравнений, в то время как двоичный поиск требует лишь логарифмического количества сравнений, определяемого числом блоков `case` в операторе `switch`. Обычно единственный способ узнать, была ли применена эта оптимизация, — это изучить сгенерированный компилятором ассемблерный код или машинный код.
Альтернативное использование
Многие языки вычисляют выражения внутри операторов switch во время выполнения, что открывает возможности для менее очевидных вариантов использования этой конструкции. Это препятствует некоторым оптимизациям компилятора, поэтому чаще встречается в динамических и скриптовых языках, где повышенная гибкость важнее, чем потери производительности.
Обработка исключений
В ряде языков программирования реализована конструкция, аналогичная оператору switch, для обработки исключений: при возникновении исключения в блоке кода выбирается отдельная ветвь в зависимости от типа этого исключения. В некоторых случаях предусмотрена также ветвь по умолчанию, которая выполняется, если исключение не возникло. Одним из первых примеров является язык Modula 3, использующий синтаксис TRY EXCEPT, где каждый блок EXCEPT определяет обработчик для конкретного случая. Аналогичный подход применяется в Delphi, Scala и Visual Basic NET.