C++. Бархатный путь. Часть 1 - Схема выполнения оператора switch
ОГЛАВЛЕНИЕ
Схема выполнения оператора switch
Рассмотрим, наконец, схему выполнения оператора switch:
- вычисляется выражение в круглых скобках после оператора switch (предварительная стадия);
- это значение последовательно сравнивается со значениями константных выражений за метками case (стадия определения начальной точки выполнения оператора);
- если значения совпадают, управление передаётся соответствующему помеченному оператору (стадия выполнения);
- если ни одно значение не совпадает и в теле оператора case есть оператор, помеченный меткой default, управление передаётся этому оператору (но даже в этом случае сочетание объявления с инициализацией недопустимо!) (стадия выполнения);
- если ни одно значение не совпадает, и в теле оператора case нет оператора, помеченного меткой default, управление передаётся оператору, следующему за оператором switch (стадия выполнения).
Метки case и default в теле оператора switch используются лишь при начальной проверке, на стадии определения начальной точки выполнения тела оператора. На стадии выполнения все операторы от точки выполнения и до конца тела оператора выполняются независимо от меток, если только какой-нибудь из операторов не передаст управление за пределы оператора выбора. Таким образом, программист сам должен заботиться о выходе из оператора выбора, если это необходимо. Чаще всего для этой цели используется оператор break.
В этом разделе нам остаётся обсудить ещё один вопрос. Это вопрос о соответствии оператора выбора и условного оператора. На первый взгляд, оператор выбора легко может быть переписан в виде условного оператора. Рассмотрим в качестве примера следующий оператор выбора:
int intXXX;
:::::
switch (intXXX)
{
case 1:
int intYYY;
/* Здесь инициализация переменной запрещена, однако определение
переменной должно выполняться. */
break;
case 2:
case 3:
intYYY = 0;
break;
}
Казалось бы, этот оператор выбора может быть переписан в виде условного оператора:
int intXXX;
:::::
if (intXXX == 1)
{
int intYYY = 0; // Здесь допускается инициализация!
}
else if (intXXX == 2 || intXXX == 3)
{
intYYY = 0;
/*
Здесь ошибка! Переменная intYYY не объявлялась в этом блоке операторов.
*/
}
Если в операторе выбора используется локальная переменная, то для всего множества помеченных операторов из блока оператора выбора требуется единственное объявление этой переменной (лишь бы она не инициализировалась).
В условном операторе переменная должна объявляться в каждом блоке.
Ситуация с необъявленной в одном из блоков условного оператора переменной может быть решена путём создания внешнего блока, в который можно перенести объявления переменных, которые должны использоваться в блоках условного оператора.
int intXXX;
:::::
if (1)
/*
Этот условный оператор определяет внешний блок операторов, в котором
располагается объявление переменной intYYY.
*/
{
int intYYY = 0;
if (intXXX == 1)
{
intYYY = 0;
}
else if (intXXX == 2 || intXXX == 3)
{
intYYY = 0;
}
}
Нам удалось преодолеть проблемы, связанные с областями действия, пространствами и областями видимости имён путём построения сложной системы вложенных блоков операторов. Простой одноблочный оператор выбора, содержащий N помеченных операторов, моделируется с помощью N+1 блока условных операторов.
Однако каждый оператор хорош на своём месте.