Чому булівський тип у C ++ підтримує ++, але ні -?


29

Чому оператор --не існує для bool, а для оператора ++?

Я спробував C ++, і не знаю, чи стосується мого питання до іншої мови. Я також буду рада знати.

Я знаю , я можу використовувати оператора ++з bool. Це робить будь-який бул рівним справжньому.

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

Чому ми не можемо використовувати оператора --протилежним чином?

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

Це не дуже корисно, але мені цікаво.


8
Це питання на StackOverflow може бути освічуючим.
Blrfl

Так історія причина. Дякую за посилання Чи можете ви написати відповідь, і я поставив її як вирішену?
aloisdg повідомляє про відновлення Моніки

Самі посилання не дають хороших відповідей, і немає хорошого механізму для позначення питання тенісу дублікатами чогось на іншому веб-сайті SE.
Blrfl

1
Отже, ми повинні відкрити тему в meta.stackexchange.com чи щось. Я думаю, ви повинні отримати карму для хорошого зв’язку, і якщо хтось висловиться за вас, автор з оригінальної відповіді повинен отримати карму. Насправді оригінальне запитання також повинно отримати карму.
aloisdg повідомляє про відновлення Моніки

2
@aloisdg перехресні сайти - це старе питання MSO. Переслідуйте пов'язані питання, щоб отримати більш повне уявлення про нього.

Відповіді:


53

За старих часів С булевого типу не було. Люди використовували intдля зберігання булевих даних, і це працювало здебільшого. Нуль був помилковим, а все інше було правдою.

Це означало, що якщо ви взяли int flag = 0;і пізніше зробили flag++це значення, було б істинним. Це спрацювало б незалежно від значення прапора (якщо ви цього багато не зробили, він перекинувся і ви повернулися до нуля, але нехтуєте цим) - збільшення прапора, коли його значення було 1, дало б 2, яке все ще було правда.

Деякі люди використовували це для безумовного встановлення булевого значення true. Я не впевнений, що це колись стало ідіоматичним , але це є в деякому коді.

Це ніколи не спрацьовувало --, оскільки якби значення було чимось іншим, ніж 1 (яке воно могло бути), значення все одно не було б помилковим. І якби воно вже було false ( 0), і ви зробили оператор decrement на ньому, він не залишився б false.

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

Значення, отримане за допомогою застосування постфікса ++, є значенням, яке операнд мав перед застосуванням оператора. [Примітка: отримане значення є копією вихідного значення] Операнд має змінюватися значення. Тип операнда має бути арифметичним типом або вказівником на тип цілісного об'єкта. Після того, як результат буде відзначений, значення об'єкта змінюється додаванням до нього 1, крім випадків, коли об’єкт не має типу bool, і в цьому випадку він встановлюється в true. [Примітка: це використання застаріло, див. Додаток D.]

Операнд Postfix - зменшується аналогічно оператору postfix ++, за винятком того, що операнд не повинен мати тип bool.

Це знову згадується у розділі 5.3.2 (для оператора префікса - на постфіксі був 5.2.6)

Як бачите, це застаріле (додаток D у документі, сторінка 709) і не повинно використовуватись.

Але ось чому. І іноді ви можете побачити код. Але не робіть цього.


5
"Деякі люди використовували це для безумовного встановлення булевого значення в істинне". Назвемо їх проклятими дурнями, а не людьми.
Дедуплікатор

@Deduplicator: Можливо, це було справою продуктивності: завантаження значення в змінну, можливо, зайняло більше циклів процесора, ніж збільшення змінної. Звичайно, це, мабуть, не має значення на сучасних комп’ютерах.
Джорджо

1
@Giorgio це цілком ймовірно. Пам'ятайте, що C було написано так, щоб воно відповідало набору інструкцій PDP-7, а PDP-11 мав інші зміни. Від цього - «Люди часто думають , що вони були створені , щоб використовувати режими адреси автоінкрементіруемих і авто-декремент , що надається DEC PDP-11 , на якому C і Unix першого стали популярними Це історично неможливо, так як не було ніякого PDP - . 11, коли було розроблено B. Однак PDP-7 мав кілька комірок пам'яті з автоматичним збільшенням з властивістю того, що непряме посилання на пам'ять через них збільшувало осередок ".

@Deduplicator: У коді, який використовує цілі числа для булевих значень, змінна, що збільшується для кожного ... що завгодно ... може виступати як лічильником (у скільки разів він був збільшений), так і як булевим (чи був він збільшений у всіх або ні).
Кіт Томпсон


1

Щоб зрозуміти історичне значення цього питання, ви повинні розглянути випадок "Терака-25". Therac-25 був медичним пристроєм, який доставляв радіацію хворим на рак. Він зазнав поганих практик програмування, що сприяло його слабкому досвіду безпеки (з ним приписувались численні випадки смерті).

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

(перейти до нижньої частини сторінки 3)

Кожен прохід через програму Set-Up Test збільшує перевірку положення верхнього коліматора, загальну змінну під назвою Class3. Якщо Клас3 ненульовий, існує невідповідність, і лікування не слід продовжувати. Нульове значення для класу 3 вказує на те, що відповідні параметри відповідають обробці, і промінь не гальмується.

...

Під час налаштування машини тест налаштування буде виконуватися декілька сотень разів, оскільки він переноситься на очікування інших подій. У коді змінна Class3 збільшується по одній на кожен прохід через тест налаштування. Оскільки змінна Class3 становить 1 байт, вона може містити лише максимальне значення 255 десятків. Таким чином, кожного 256-го проходу через тестовий код налаштування змінна переповнює і має нульове значення. Це означає, що на кожному 256-му проходженні через тест налаштування верхній коліматор не перевірятиметься і несправність верхнього коліматора не буде виявлена. Перенапруження сталося, коли оператор натиснув кнопку «встановити» в той самий момент, коли Class3 перекинувся на нуль. Таким чином, Чккол не був виконаний, і 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типом. Я просто намагався дати історичний приклад того, коли люди насправді програмували так.
Девід Стоун
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.