Почему bool и не bool оба возвращают true в этом случае? [дубликат]


этот вопрос уже есть ответ здесь:

  • Инженерный bool сравнивается равным как истинным, так и ложным, почему? 5 ответов

это мой код:

#include <cstring>
#include <iostream>
int main() {
    bool a;
    memset(&a, 0x03, sizeof(bool));
    if (a) {
        std::cout << "a is true!" << std::endl;
    }
    if (!a) {
        std::cout << "!a is true!" << std::endl;
    }
}

он выводит:

a is true!
!a is true!

кажется,! оператор on bool инвертирует только последний бит, но каждое значение, которое не равно 0 трактуется как true. Это приводит к показанному поведению, которое логически неверно. Это ошибка в реализации, или спецификация позволяет это? Обратите внимание, что memset можно опустить, и поведение будет наверное быть таким же, потому что a содержит мусора.

Я на gcc 4.4.5, другие компиляторы могут сделать это по-другому.

3 68

3 ответа:

стандарт (3.9.1 / 6 фундаментальных типов) говорит:

значения типа bool являются либо истинными, либо ложными.

....

использование значения bool способами, описанными в этом международном стандарте как "неопределенные", например, путем изучения значения неинициализированный автоматический объект может заставить его вести себя так, как будто он не является ни истинным, ни ложным.

ваша программа использует memset приводит к неопределенному поведению. Последствие что может быть, что значение не является ни истинным, ни ложным.

Это не "логически неправильно", это неопределенное поведение. bool должно содержать только одно из двух значений,true или false. Присвоение ему значения приведет к преобразованию в одно из этих значений. Нарушение безопасности типа путем записи произвольного значения байта поверх его памяти (или, как вы упомянули, оставляя его неинтиализированным) не будет, поэтому вы вполне можете получить значение, которое не является ни true, ни false.

внутренне это, вероятно, с помощью побитового не (~ оператор), чтобы инвертировать его, который будет работать, когда bool был либо нулем, либо всеми:

 a = 00000000 (false)
!a = 11111111 (true)
Если вы установите его на три:
 a = 00000011 (true)
!a = 11111100 (also true)