Почему логический тип в C ++ поддерживает ++, а не -?

29

Почему оператор --не существует для bool, а для оператора ++?

Я пробовал в C ++, и я не знаю, относится ли мой вопрос к другому языку. Я буду рад узнать также.

Я знаю , я могу использовать оператор ++с бул. Это делает любое bool равным истине.

bool b = false;
b++;
// Now b == true.

Почему мы не можем использовать оператор --противоположным образом?

bool b = true;
b--;
// Now b == false;

Это не очень полезно, но мне любопытно.

Aloisdg говорит восстановить Монику
источник
8
Этот вопрос о StackOverflow может быть полезным.
Blrfl
Так что история причина. Спасибо за ссылку. Можете ли вы написать ответ, и я поставил его как решено?
Aloisdg говорит восстановить Монику
Одни только ссылки не дают хороших ответов, и нет хорошего механизма для того, чтобы пометить tnis вопрос дубликатом чего-либо на другом сайте SE.
Blrfl
1
Поэтому мы должны открыть тему в meta.stackexchange.com или что-то в этом роде. Я думаю, что вы должны получить некоторую карму за хорошую ссылку, и если кто-то поддержит вас, автор оригинального ответа должен получить некоторую карму. На самом деле, оригинальный вопрос тоже должен получить некоторую карму.
Aloisdg говорит восстановить Монику
2
@aloisdg межсайтовые ошибки - старая проблема MSO. Преследуйте связанные вопросы, чтобы получить более полное представление об этом.

Ответы:

53

В старые времена C не было никакого логического типа. Люди использовали intдля хранения логических данных, и это работало в основном. Ноль был ложным, а все остальное было правдой.

Это означало, что если вы взяли, int flag = 0;а потом сделали, flag++значение было бы истинным Это будет работать независимо от значения флага (если вы не сделали этого много, он перевернулся, и вы вернулись к нулю, но давайте проигнорируем это) - при увеличении значения флага, равного 1, будет 2, что все еще правда.

Некоторые люди использовали это для безоговорочной установки логического значения в true. Я не уверен, что это когда-либо стало идиоматическим , но это в некотором коде.

Это никогда не работало --, потому что если бы значение было чем-то отличным от 1 (что могло бы быть), значение все равно не было бы ложным. И если оно уже было ложным ( 0), и вы применили оператор декремента, оно не останется ложным.

При переходе кода с C на C ++ в первые дни было очень важно, чтобы код на C, включенный в C ++, все еще мог работать. И поэтому в спецификации для C ++ (раздел 5.2.6 (на странице 71)) он гласит:

Значение, полученное путем применения postfix ++, является значением, которое операнд имел до применения оператора. [Примечание: полученное значение является копией исходного значения] Операндом должно быть изменяемое значение l. Тип операнда должен быть арифметическим типом или указателем на полный тип объекта. После того, как результат отмечен, значение объекта изменяется, добавляя 1 к нему, если объект не имеет тип bool, в этом случае это установлено в true. [Примечание: это использование устарело, см. Приложение D.]

Операнд постфикса - уменьшается аналогично оператору постфикса ++, за исключением того, что операнд не должен иметь тип bool.

Это снова упоминается в разделе 5.3.2 (для префиксного оператора - 5.2.6 был на постфиксе)

Как видите, это устарело (Приложение D в документе, стр. 709) и не должно использоваться.

Но вот почему. И иногда вы можете увидеть код. Но не делай этого.

Сообщество
источник
5
«Некоторые люди использовали это для безоговорочной установки логического значения в true». Давайте назовем их проклятыми дураками, а не людьми.
дедупликатор
@Deduplicator: Возможно, это был вопрос производительности: загрузка значения в переменную может занять больше процессорных циклов, чем приращение переменной. Конечно, это, вероятно, не имеет значения на современных компьютерах.
Джорджио
1
@ Джорджио, что вполне вероятно. Помните, что C был написан так, чтобы точно соответствовать набору инструкций PDP-7, а в PDP-11 были другие настройки. От этого - «Люди часто думают , что они были созданы , чтобы использовать режимы адреса автоинкрементируемых и авто-декремент , предоставляемый DEC PDP-11 , на котором C и Unix первого стали популярными Это исторически невозможно, так как не было никакого PDP - . 11, когда был разработан B. Однако PDP-7 действительно имел несколько ячеек памяти с «автоматическим приращением» со свойством, что косвенная ссылка на память через них увеличивала ячейку ».
@Deduplicator: В коде, который использует целые числа для логических значений, переменная, которая увеличивается для каждого ... чего угодно ... может действовать как счетчик (во сколько раз он был увеличен) и как логическое значение (было ли оно увеличено вообще или не).
Кит Томпсон
2

Частично справиться с унаследованным кодом, который использовал intили похож на его логический тип.

Майк Грэм
источник
1
Мой вопрос является дубликатом здесь stackoverflow.com/questions/3450420/… . Кстати, спасибо за ваш ответ.
Aloisdg говорит восстановить Monica
1

Чтобы понять историческое значение этого вопроса, вы должны рассмотреть случай с Therac-25. Therac-25 был медицинским устройством, которое доставляло излучение больным раком. Его преследовали плохие методы программирования, которые способствовали его плохой репутации в области безопасности (с несколькими приписанными ему смертями).

http://courses.cs.vt.edu/professionalism/Therac_25/Therac_1.html

(перейти к нижней части страницы 3)

Каждый проход процедуры проверки настройки увеличивает проверку положения верхнего коллиматора, общую переменную с именем Class3. Если Class3 отличен от нуля, существует несоответствие, и лечение не должно продолжаться. Нулевое значение для Class3 указывает, что соответствующие параметры согласуются с обработкой, и луч не блокируется.

...

Во время настройки машины тест настройки будет выполняться несколько сотен раз, так как он перепланирует себя в ожидании других событий. В коде переменная Class3 увеличивается на единицу при каждом прохождении теста настройки. Поскольку переменная Class3 составляет 1 байт, она может содержать только максимальное значение 255 десятичных. Таким образом, при каждом 256-м проходе кода проверки настройки переменная переполняется и имеет нулевое значение. Это означает, что при каждом 256-м проходе теста настройки верхний коллиматор не будет проверяться, и неисправность верхнего коллиматора не будет обнаружена. Передержка произошла, когда оператор нажал кнопку «установить» в тот момент, когда Class3 перешел на ноль. Таким образом, Chkcol не был выполнен, а F $ mal не был установлен, чтобы указывать, что верхний коллиматор все еще находился в положении полевого света. Программное обеспечение включило все 25 МэВ без цели на месте и без сканирования. В результате получился высококонцентрированный электронный пучок, который рассеивался и отклонялся зеркалом из нержавеющей стали, которое было на пути.

Therac-25 использовал что-то вроде эквивалента operator++на a bool. Однако язык программирования, который они использовали, не был C ++, а их тип данных - нет bool. В отличие от гарантии в C ++, обычный целочисленный тип просто продолжает расти. Их тип данных был эквивалентом uint8_t.

C ++ решил оставить operator++людей, привыкших к программированию подобным образом, но вместо того, чтобы увеличивать значение, он просто устанавливает его trueдля предотвращения подобных вещей.

Обратите внимание, что operator++(bool)не рекомендуется.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf

Приложение D к C ++ 14:

D.1 Оператор приращения с операндом bool
Использование операнда типа bool с оператором ++ не рекомендуется (см. 5.3.2 и 5.2.6).

Дэвид Стоун
источник
Хотя это и объясняет, почему оно устарело, но не объясняет, почему оно вообще существует.
Он существует потому, что некоторые люди устанавливали логическое значение, увеличивая его при программировании на C. C ++ был разработан, чтобы облегчить переход с C, поэтому они поддерживали его с boolтипом. Я просто пытался привести исторический пример того, когда люди действительно программировали таким образом.
Дэвид Стоун