C ++: чому bool становить 8 біт?


132

У мові C ++ мені цікаво, чому тип bool дорівнює 8 біт (у моїй системі), де достатньо лише одного біта для утримання булевого значення?

Раніше я вважав, що це з міркувань продуктивності, але тоді на 32-бітній або 64-бітовій машині, де регістри шириною 32 або 64 біти, яка перевага від продуктивності?

Або це лише одна з цих «історичних» причин?


9
Буль - це не 8 біт у моїй системі. Це 4 байти, те саме, що і int.
Брайан Ніл

21
востаннє хтось думав про те, що ти думаєш, ми закінчили std :: vector <bool>, найнависніший stl "особливість" коли-небудь =)
Viktor Sehr

1
jldupont, я думаю, ти мене неправильно прочитав. Я запитував систему, де sizeof(bool)було б 4. Я міг би посягнути, що у msvc було 32-бітових булів, але я просто спробував, і це не так.
авакар

7
Якщо чесно, проблема vector<bool>полягає не в тому, що він намагається бути розумним і упакувати булі в біти, а в тому, що він намагається це зробити і маскуватися під контейнер STL . Звичайний біт був би добре, доки він також не видаватиметься контейнером STL.
jalf

2
@avakar - можливо, ви плутаєте boolтип даних C ++ з типом Windows, для BOOLякого встановлено тип long. Отже sizeof(bool) != sizeof(BOOL), що я впевнений, викликає багато плутанини (і, мабуть, неабияку кількість помилок). Тим більше, що в Windows також є booleanі BOOLEANtypedefs, які є псевдонімами для unsigned char. Також зауважте, що хоча це звичайно bool1 байт, стандарт C ++ має примітку, яка конкретно вказує, що sizeof(bool)може бути більшим.
Майкл Берр

Відповіді:


219

Тому що кожен тип даних C ++ повинен бути адресованим.

Як би ви створили покажчик на один біт? Ви не можете. Але ви можете створити вказівник на байт. Таким чином, булева величина в C ++ має типовий розмір байтів. (Він може бути і більшим. Це залежить від реалізації. Головне, щоб він був адресованим, тому жоден тип даних C ++ не може бути меншим за байт)


7
"байт" адресація є архітектурним вибором (рівень hw): можна дуже добре спроектувати систему з іншою "одиницею адресації". Для звичайних процесорів звернення до "байту" в будь-якому випадку отримує більше, ніж "байт" із зовнішньої пам'яті: це пов'язано з причинами ефективності.
jldupont

8
Так, це апаратний вибір, і якщо апаратне забезпечення це дозволяє, розмір bool може змінитися. Але ОП запитав, чому bool шириною 8 біт, а в системах, де це так, це, як правило, тому, що процесор здатний адресувати лише 8-бітні байти.
jalf

2
@jldupont: Є декілька систем, де адреси вказівників є більш дрібними, ніж байти (я програмував на старому TI TMS34010 / 20 раніше, де використовуються біт-мудрі покажчики), але вони ВЖЕ рідкісні.
Майкл Коне

1
Не впевнений, що ти маєш на увазі. Кожен об'єкт повинен бути адресованим, тобто має бути можливість отримати адресу об’єкта. Об'єкт не повинен зберігати власну адресу. Типовий знак char зазвичай становить 8 біт, достатній для зберігання будь-якого з 256 символів, але кожен char також має адресу, визначену тим, де в пам'яті він знаходиться. Ось чому ви можете створити покажчик на таблицю.
jalf

88
Якщо я можу внести сумнівну аналогію: у моїй будівлі вісім поверхів, але пошта не визнає, що це різні адреси. Тож, якщо я хочу адресувати все собі, тоді я повинен взяти в оренду всю будівлю, хоча я фактично розміщуюся на одному поверсі. Я не використовую інші сім поверхів для "зберігання адреси", я просто змушений їх марнувати через правило Поштового відділення, яке стосується будівель, а не поверхів. Об'єкти C ++ повинні мати адресу для себе - немає поштових кабінетів, щоб сортувати пошту після доставки ;-)
Стів Джессоп

39

Пам'ять адресована байтом. Ви не можете адресувати один біт, не зміщуючи чи маскуючи прочитаний байт із пам'яті. Я думаю, це дуже велика причина.


1
Не завжди. 8051 MCU, наприклад, має 16 байт розташування битих адресованих
мілині

20

booleanТипу , який зазвичай слідує за найменшу одиницю адресується пам'яті цільової машини (тобто , як правило, 8bits байт).

Доступ до пам’яті завжди є «шматками» (кілька слів, це для ефективності на апаратному рівні , транзакцій на шині): булевий біт не може бути адресований «поодинці» у більшості системних процесорів. Звичайно, щойно дані містяться в реєстрі , часто існують спеціалізовані інструкції щодо самостійного маніпулювання бітами.

З цієї причини досить часто застосовується техніка "бітової упаковки" для підвищення ефективності використання "булевих" базових типів даних. Такий прийом, як enum(у С) потужністю 2 кодування, є хорошим прикладом. Така ж хитрість є в більшості мов.

Оновлено : Завдяки чудовій дискусії, мені було показано, що sizeof(char)==1за визначенням в C ++. Отже, адресація "булевого" типу даних досить прив’язана до найменшої одиниці адреси, що запам'ятовується (підкреслює мою думку).


На всі коментарі, які ви залишили з цього приводу, вражає, що ви залишили найважливішу частину відповіді: boolтип слідує за найменшою одиницею пам'яті, що виділяється, оскільки C ++ вимагає, щоб було можливо створити покажчики на неї . Без цієї вимоги boolможна було б представити як єдиний біт навіть на поточних машинах, адресованих байтами.
jalf

1
Хммм ... Я міг би створити архітектуру процесора, де трохи можна було б адресувати ... Я навіть міг написати компілятор тощо. Я міг би мати спеціальну область пам'яті (або будь-яку іншу), яка була б "бітова адресація". Це ніяким розтягненням уяви неможливо.
jldupont

2
Так, і в цій системі може бути зроблено bool, щоб він був єдиним бітом. Але ОП не запитувало "чому бул 8 біт шириною на гіпотетичному процесорі jlduponts". Він запитав про поточні, звичайні, повсякденні процесори, а про них - це тому, що вони адресовані байтам.
jalf

4
sizeof (char) == 1 на визначення в C ++, тому те, що може або не може зробити ваше обладнання, не має значення. Ви не можете мати sizeof (bool) <sizeof (char). BTW C ++ визначений таким чином, що ви можете мати "жирний" покажчик, щоб вирішити якусь субодиницю того, до чого може звернутися апаратне забезпечення, якщо не зручно мати найменший апаратний адресний блок. Це було використано принаймні в деяких компіляторах C для старих архітектур, що адресуються словом.
AProgrammer

@AProgrammer:: sizeof(char)==1 definitionце найкращий контраргумент моїй аргументації. Дякую!
jldupont

6

Відповіді про 8-бітну найменшу кількість пам'яті, яку можна адресувати, є правильними. Однак деякі мови певним чином можуть використовувати 1-розрядний для булевих значень. Здається, я пам’ятаю набори реалізації Pascal як бітові рядки. Тобто для наступного набору:

{1, 2, 5, 7}

Ви можете мати це в пам'яті:

01100101

Звичайно, ви можете зробити щось подібне в C / C ++, якщо хочете. (Якщо ви відстежуєте купу булів, це може мати сенс, але це дійсно залежить від ситуації.)


8
Фактично, C ++ робить це за допомогою спеціалізованого вектора контейнерів <bool> - це зазвичай сприймається як катастрофа.

C ++ також робить це з "бітовими полями", успадкованими від C. При оголошенні змінної члена структури / класу ви можете оголосити кількість бітів, використаних для зберігання значення (наприклад, "неподписане коротке поле: 3").

@Neil: чому це зазвичай сприймається як катастрофа? Це проблема продуктивності?
Jérôme

2
@Jerome: Це тому, що, оскільки трохи не адресовано, він не може вести себе як звичайний vector. Насправді це контейнер типу STL, оскільки є обмеження в поведінці. Найгірше те, що це створює проблеми з тим, хто має когось boolі хоче зробити vectorз них. Це дивна поведінка, і це не те, що ви хочете мовою.
Девід Торнлі

1
@jldupont - достатньо одного разу зробити таку точку. І C ++ не дає гарантії, що біти адресовані (скоріше зворотно), незалежно від того, на що здатне обладнання.

1

Я знаю, що це по-старому, але я думав, що кину свої 2 копійки.

Якщо ви обмежите булевий або тип даних одним бітом, то ваша програма загрожує руйнуванням пам'яті. Як ви обробляєте статистику помилок у пам'яті, яка триває лише один біт?

Я пішов на співбесіду на роботу, і одне із заяв керівника програми мені сказало: "Коли ми надсилаємо сигнал для запуску ракети, ми просто надсилаємо простий один біт на вимкнений біт по бездротовій передачі. Надсилання одного біта надзвичайно швидко, і ми потрібен цей сигнал, щоб він був якомога швидшим ".

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


Задайте нове запитання , не публікуйте своє запитання як відповідь на інші запитання.
Ігор Єросиміч

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

1
@StephenHolt, але це не причина, і TBH ця відповідь не має ніякого сенсу.
doc

1
...що? Я не знаю, що ви маєте на увазі під "статистикою помилок", чи це КРС, чи подібні, або представлення пасток. Але в будь-якому випадку, навіть більші типи не використовують свої додаткові "запасні" біти для "статистики помилок", оскільки всі кодери, крім екстремальних середовищ, правильно вважають, що їх обладнання може обробляти виявлення / виправлення помилок до того, як їх код колись прочитає пам'ять, тому вони не потрібно витрачати свій час якось набиваючи кожну змінну інформацією про підтвердження чи будь-що інше. Ось чому не boolвикористовується 8 біт на машині OP і 32 на моїй, оскільки ті інші 7 або 31 біт, безумовно, не використовуються для жодної "статистики помилок". Це не має сенсу
підкреслити

1

Деякі вбудовані компілятори мають тип int1, який використовується для розфасовки булевих прапорів (наприклад, серія C-компіляторів CCS для Microchip MPU). Встановлення, очищення та тестування цих змінних використовує інструкції рівня бітового рівня з однією інструкцією, але компілятор не дозволить проводити будь-які інші операції (наприклад, взяття адреси змінної) з причин, зазначених в інших відповідях.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.