- Это хорошо? (это было протестировано с g ++ 4.3.3) Я имею в виду, должен ли компилятор знать, что во время логического сравнения любое ненулевое значение может означать true?
Любое целочисленное значение, отличное от нуля (или указатель, отличный от NULL), представляет собой значение true.
Но при сравнении целых и bool перед сравнением bool преобразуется в int.
- Знаете ли вы случай, когда этот угловой случай может стать реальной проблемой? (Например при двоичной загрузке данных из потока)
Это всегда реальная проблема.
Это нормально?
Я не знаю, указывают ли спецификации что-либо об этом. Компилятор всегда может создать такой код: ((a! = 0) && (b! = 0)) || ((a == 0) && (b == 0)) при сравнении двух логических значений, хотя это может снизить производительность.
На мой взгляд, это не ошибка, а неопределенное поведение. Хотя я думаю, что каждый разработчик должен сообщать пользователям, как в их реализации выполняются логические сравнения.
Если мы пойдем по последнему примеру кода, и a и b будут bool и установлены в true, присваивая 1 и 2 с уважением (Нет, 1 и 2 исчезают, теперь они просто верны).
Итак, сломав ваше выражение:
a!=0 // true (a converted to 1 because of auto-type conversion)
b!=0 // true (b converted to 1 because of auto-type conversion)
((a!=0) && (b!=0)) => (true && true) // true ( no conversion done)
a==0 // false (a converted to 1 because of auto-type conversion)
b==0 // false (b converted to 1 because of auto-type conversion)
((a==0) && (b==0)) => (false && false) // false ( no conversion done)
((a!=0) && (b!=0)) || ((a==0) && (b==0)) => (true || false) => true
Так что я бы всегда ожидал, что приведенное выше выражение будет хорошо определенным и всегда верным
Но я не уверен, как это относится к вашему первоначальному вопросу. При назначении целого числа bool целое число преобразуется в bool (как описано несколько раз). Фактическое представление истины не определено стандартом и может быть любым битовым шаблоном, который умещается в bool (вы не можете предполагать какой-либо конкретный битовый шаблон).
При сравнении bool с int bool сначала конвертируется в int, а затем сравнивается.
Любой случай из реальной жизни
Единственное, что приходит мне в голову, если кто-то читает двоичные данные из файла в структуру, в которой есть члены bool. Проблема может возникнуть, если файл был создан другой программой, написавшей 2 вместо 1 вместо bool (возможно, потому что он был написан на другом языке программирования).
Но это может означать плохую практику программирования.
Запись данных в двоичном формате непереносима без знания.
Есть проблемы с размером каждого объекта.
Есть проблемы с представлением:
- Целые числа (имеют порядковый номер)
- Float (представление не определено ((обычно зависит от базового оборудования))
- Bool (двоичное представление не определено стандартом)
- Структура (отступы между элементами могут отличаться)
Со всем этим вам нужно знать базовое оборудование и компилятор. Разные компиляторы или разные версии компилятора или даже компилятор с разными флагами оптимизации могут иметь разное поведение для всего вышеперечисленного.
Проблема с Союзом
struct X
{
int a;
bool b;
};
Поскольку люди упоминают, что пишут в 'a', а затем читают из 'b', оно не определено.
Почему: потому что мы не знаем, как 'a' или 'b' представлены на этом оборудовании. Запись в «а» заполнит биты в «а», но как это отразится на битах в «б». Если ваша система использовала 1 байт bool и 4 байта int с младшим байтом младшего байта в старшем байте старшей памяти, то запись 1 в 'a' приведет к 1 в 'b'. Но тогда как ваша реализация представляет собой bool? Является ли истина представленной 1 или 255? Что произойдет, если вы поставите 1 в 'b' и для всех других случаев использования true он использует 255?
Так что, если вы не понимаете и свое оборудование, и ваш компилятор, поведение будет неожиданным.
Таким образом, эти виды использования не определены, но не запрещены стандартом. Причина, по которой им это разрешено, заключается в том, что вы, возможно, провели исследование и обнаружили, что в вашей системе с этим конкретным компилятором вы можете выполнить некоторую простую оптимизацию, сделав эти предположения. Но имейте в виду, что любые изменения в предположениях нарушат ваш код.
Кроме того, при сравнении двух типов компилятор будет выполнять некоторые автоконвертации перед сравнением, помните, что оба типа преобразуются в один и тот же тип перед сравнением. Для сравнения между целыми числами и bool bool конвертируется в целое число, а затем сравнивается с другим целым числом (преобразование преобразует false в 0 и true в 1). Если оба объекта являются булевыми, тогда преобразование не требуется, и сравнение выполняется с использованием логической логики.