Pull to refresh

Когда переменная bool не true и не false одновременно

Reading time 2 min
Views 36K
Недавно читали код и наткнулись на примерно такой такой фрагмент.

bool *t = new bool[X][Y];
// много строк
switch (t[M][N])
{
case true:
        // много строк
        break;
case false:
        // много строк
        break;
default:
        // много строк
        break;
}

Сразу возникает вопрос: зачем нужна ветка default? Если переменная не равна true, то она равна false. Однокурсник сказал: «Для отладки». Думаю: что тут можно отлаживать? Но не всё так просто.

Запускаю. Выполняется код в ветке default. Самое первое предположение — забыли поставить break. Внимательно перечитываю код — всё в порядке. Запускаю в отладчике и замечаю, что выполняется сразу ветка default, а в ветку true или false даже не заходит. Решаю просмотреть значение переменной. Visual Studio 2012 запущенная на Windows 7 показывает 205. Допустим. Плюсы я стал учить недавно, поэтому решил провести небольшой опыт: создал булевую переменную и присвоил ей 205. Отрабатывает ветка true. Пока я размышлял над этой проблемой, однокурсник нашёл решение этой проблемы: оказывается, массив не был инициализирован. После инициализации проблема исчезла. Теперь у меня возник возник вопрос: неужели проблема в switch? Ради проверки я решил провести следующий опыт.

#include <iostream>
using namespace std;

int main() {
    bool *t = new bool[1];
    switch (t[0])
    {
    case true:
        cout << "true\n";
        break;
    case false:
        cout << "false\n";
        break;
    default:
        cout << "superposition\n";
        break;
    }
    if(t[0] == true) {
        cout << "true\n";
    } else if(t[0] == false) {
        cout << "false\n";
    } else {
        cout << "superposition\n";
    }
    if(t[0]) {
        cout << "true\n";
    } else if(!t[0]) {
        cout << "false\n";
    } else {
        cout << "superposition\n";
    }
    delete[] t;
    return 0;
}

Вариант с switch или первый вариант с if позволяет определить не инициализированную булевую переменную. Второй вариант с if никогда не заходит в третий вариант.

Как создать такую переменную Шрёдингера? Создайте динамический или статический массив. Используйте его перед инициализацией. А также, самое вкусное, то, что вы можете скопировать это неопределённое значение, даже в скалярную переменную. Где это может пригодится — решать вам.

Интересно также то, что если перед проверкой вставить:

char a = t[0];
t[0] = a;
то переменная наконец-то станет true. А если написать
bool a = t[0];
t[0] = a;


то ничего не изменится.

Позднее я повторил опыт на Visual Studio 2013 с 5 пакетом обновления запущенная на Windows 7. Там отладчик говорит, что неинициализированная переменная равна true, но несмотря на это в блок true не заходит. Также она говорит, что ветка default не нужна, так как все возможные метки уже заданы. Но несмотря на это заходит в блок default.

В Linux данная особенность не проявляется.
Tags:
Hubs:
+24
Comments 54
Comments Comments 54

Articles