Могу ли я предположить (bool) true == (int) 1 для любого компилятора C ++?

118

Могу я предположить (bool)true == (int)1для любого компилятора C ++?

Petruza
источник
3
Приведения в вашем вопросе избыточны, следует ли их поменять местами?
GManNickG
9
Он не имел в виду, что они должны быть bool t = true; int n = 1; if (t == n) {...} ;
кастами
7
@egrunin: Эх, но true - это логическое значение, а 1 в любом случае - это int. :)
GManNickG
1
Правильно, я хотел указать тип значений.
Петруза
2
(int) trueявляется 1целым числом, но что-то вроде if (pointer)проходит через часть then if pointer != 0. Единственное, что вы можете принять за истину, это то false == 0, и true != 0trueоценивается 1при использовании int)
Луис Колорадо

Ответы:

134

Да. Приведения повторяются. В вашем выражении:

true == 1

Применяется комплексное продвижение, и значение bool будет повышено до int и это продвижение должно дать 1.

Ссылка: 4.7 [conv.integral] / 4: Если тип источника bool... trueпреобразуется в единицу.

CB Bailey
источник
9
@Joshua: trueключевое слово, определяемое языком. Библиотека не может его переопределить. #defines не разрешено переопределять ключевые слова.
jalf
21
@jalf: # define действительно разрешено определять системные ключевые слова. Фаза предварительной обработки компиляции C является чисто текстовой и ничего не знает о ключевых словах или синтаксисе C в целом. Тем не менее, конечно, почти всегда переопределять ключевые слова языка - плохая идея.
Дейл Хагглунд,
2
@jalf. Они не? См. Gcc.gnu.org/onlinedocs/cpp/Macros.html и по крайней мере одну из записей в Международном конкурсе запутанного кода C, который однажды спросил: «Когда whileне нужно время?» : (Ответ , когда он принимает два параметра, потому что тогда , что запись была #definedего printf.)
Ken Bloom
3
В C99, §6.10.1 / 1 сказано: «Выражение, управляющее условным включением, должно быть целочисленным постоянным выражением, за исключением того, что: оно не должно содержать приведение; идентификаторы (включая те, которые лексически идентичны ключевым словам) интерпретируются, как описано ниже;» Хотя это и не указано как прямое разрешение, это явно предполагает возможность макроса, который «лексически идентичен» ключевому слову.
Джерри Коффин,
2
Да, и #defines позволяет переопределять ключевые слова. C ++ 1x вызвал слишком много проблем с новыми ключевыми словами, поэтому это требование пришлось удалить.
Джошуа
18

Ответ Чарльза Бейли правильный. Точная формулировка из стандарта C ++ (§4.7 / 4): «Если исходный тип - bool, значение false преобразуется в ноль, а значение true преобразуется в единицу».

Изменить: я вижу, что он тоже добавил ссылку - я скоро удалю это, если я не отвлекусь и не забуду ...

Edit2: Опять же, вероятно, стоит отметить, что, хотя сами логические значения всегда преобразуются в ноль или единицу, ряд функций (особенно из стандартной библиотеки C) возвращают значения, которые являются «в основном логическими», но представлены как ints, которые являются обычно требуется только ноль, чтобы указать ложь или ненулевое значение, чтобы указать истину. Например, для функций is * в <ctype.h>требуется только ноль или ненулевое значение, не обязательно ноль или единица.

Если вы бросите это на bool приведете , ноль преобразуется в ложь, а ненулевое значение - в истину (как и следовало ожидать).

Джерри Гроб
источник
9

Согласно стандарту, вы должны быть уверены в этом предположении. Тип C ++ boolимеет два значения - trueиfalse с соответствующими значениями 1 и 0.

Следует обратить внимание на смешивание boolвыражений и переменных с BOOLвыражениями и переменными. Последний определяется как FALSE = 0и TRUE != FALSE, что довольно часто на практике означает, что рассматривается любое значение, отличное от 0.TRUE .

Многие современные компиляторы фактически выдают предупреждение для любого кода, который неявно пытается выполнить приведение из BOOLк, boolесли BOOLзначение отличается от 0 или 1.

Франси Пенов
источник
3

Я обнаружил, что разные компиляторы возвращают разные результаты при true. Я также обнаружил, что почти всегда лучше сравнивать bool с bool вместо int. Эти целые числа имеют тенденцию изменять значение с течением времени по мере развития вашей программы, и если вы примете значение true как 1, вас могут укусить несвязанные изменения в другом месте вашего кода.

Майкл Дорган
источник
3
Это неправильный ответ для C ++, так как trueэто ключевое слово языка с определенным поведением. Если вы ссылаетесь на общепринятый макрос, например TRUE, это правильно.
Дэвид Торнли
1
Может быть, у меня был опыт работы с компиляторами C - за эти годы я провел с ними много времени. Моя точка зрения о прямом использовании математических выражений в операторах if остается в силе. У нас был код, который проверял, был ли битовый сдвиг ненулевым в if, затем кто-то другой взял то же ненулевое значение и предположил, что оно равно 1, и взорвал все. Простое преобразование в true / 1 предотвратило бы это.
Майкл Дорган
Я тоже видел такое поведение. По общему признанию, последний раз я видел это примерно в 1999 году. Я использовал GCC. Язык был C. Тем не менее, я действительно видел такое поведение.
thb