Почему 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, другие компиляторы могут сделать это по-другому.
Ответы
Ответ 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)