Подтвердить что ты не робот

Почему bool и not bool оба возвращают true в этом случае?

Это мой код:

#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!

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

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

4b9b3361

Ответ 1

Стандарт (3.9.1/6 Основные типы) гласит:

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

....

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

Использование вашей программы memset приводит к поведению undefined. Следствием этого может быть то, что значение не является ни истинным, ни ложным.

Ответ 2

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

Ответ 3

Внутри, скорее всего, используется побитовое (~ operator) инвертирование, которое будет работать, когда bool будет либо нулевым, либо все:

 a = 00000000 (false)
!a = 11111111 (true)

Однако, если вы установите его в три:

 a = 00000011 (true)
!a = 11111100 (also true)