Страница 61 из 82 Схема выполнения оператора 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 блока условных операторов. Однако каждый оператор хорош на своём месте. |