Чому булевий 1 байт, а не 1 біт розміру?


127

В C ++,

  • Чому булевий 1 байт, а не 1 біт розміру?
  • Чому не існує таких типів, як 4-бітні або 2-бітні цілі числа?

Мені не вистачає вищезазначених речей під час написання емулятора для процесора


10
У C ++ ви можете "запакувати" дані, використовуючи бітові поля. struct Packed { unsigned int flag1 : 1; unsigned int flag2: 1; };. Більшість компіляторів виділять повне unsigned int, однак вони розбираються у подвійному зміні, коли ви читаєте / пишете. Також вони самі займаються модульними операціями. Тобто unsigned small : 4атрибут має значення від 0 до 15, і коли він повинен досягти 16, він не перезапише попередній біт :)
— Матьє М.

Відповіді:


208

Тому що процесор не може адресувати нічого менше, ніж байт.


10
Чорт, зараз це незручно, сер
— Asm

31
На насправді, чотири x86 інструкції bt, bts, btrі btc можуть звернутися поодинокі біти!
— fredoverflow

11
Я думаю, що btадресує байтове зміщення, а потім тестує біт у заданому зміщенні, незалежно від того, коли вказувати адресу, яку ви вводите в байти ... Біт-літерали зміщення отримають трохи багатослівний (вибачте за каламбур).
— user7116

2
@six: Ви можете завантажити початок масиву в один реєстр, а потім відносне "бітове зміщення" в секунду. Зсув бітів не обмежується "в межах одного байта", це може бути будь-яке 32-бітове число.
— fredoverflow

4
Ну так і ні. У нас є бітфілди, і ми можемо мати вказівник бітфілда, тобто адресу + бітове число. Очевидно, що такий покажчик не був би конвертованим у недійсний * через додаткову вимогу зберігання бітового числа.
— Максим Єгорушкін

32

З Вікіпедії :

Історично байт - це кількість біт, що використовуються для кодування одного символу тексту на комп'ютері, і саме тому є основним адресованим елементом у багатьох архітектурах комп'ютерів.

Так байти основна адресується одиниця , нижче якої комп'ютерна архітектура не може вирішити. А оскільки не існує (ймовірно) комп'ютерів, які підтримують 4-бітний байт, у вас немає 4-бітових і т.д. bool

Однак якщо ви можете спроектувати таку архітектуру, яка може адресувати 4-розрядну базу як основний адресний блок, тоді ви матимете boolрозмір 4-розрядний лише на цьому комп'ютері!


4
"у вас буде розмір int розміру 4-розрядний тоді, лише на цьому комп'ютері" - ні, ви не будете, тому що стандарт забороняє CHAR_BIT бути менше 8. Якщо адресний блок в архітектурі менше 8 біт, то a Реалізація C ++ просто повинна представити модель пам'яті, яка відрізняється від основної моделі пам'яті апаратури.
— Стів Джессоп

@Steve: oops ... Я це не помітив. Видалено intі charз моєї посади.
— Наваз

1
у вас також не може бути 4-бітових bool, оскільки charце найменша адресна одиниця в C ++ , незалежно від того, що архітектура може адресувати за допомогою власних опкодів. sizeof(bool)повинно мати значення принаймні 1, а сусідні boolоб'єкти повинні мати власні адреси в C ++ , тому реалізація просто повинна зробити їх більшими і марнувати пам'ять. Ось чому бітові поля існують як особливий випадок: члени бітфілдів структури не повинні бути адресованими окремо, тому вони можуть бути меншими за розмір char(хоча ця структура все ще не може бути).
— Стів Джессоп

@ Стів Джессоп: це здається цікавим. Ви можете, будь ласка, надати мені посилання з мовної специфікації, де сказано, що charце найменша адресна одиниця в C ++?
— Наваз

3
Найближче конкретне твердження, ймовірно, становить 3,9 / 4: "Об'єктне представлення об'єкта типу T - це послідовність N неподписаних символів char, взятих об'єктом типу T, де N дорівнює sizeof (T)". Очевидно, що sizeof(bool)не може бути 0,5 :-) Я думаю, що реалізація могла б законодавчо надавати підбайтові покажчики як розширення, але "звичайні" об'єкти, такі як bool, виділяються звичайними способами, повинні робити те, що говорить стандарт.
— Стів Джессоп

12

Найпростіша відповідь; це тому, що ЦП звертається до пам'яті в байтах, а не в бітах, а бітові операції дуже повільні.

Однак можливо використовувати розподіл розміру бітів у C ++. Існує std :: векторна спеціалізація для бітових векторів, а також структури, що приймають записи розміру біт.


1
Не впевнений, я погодився б, що побітні операції проходять повільно. ands, nots, xors тощо дуже швидко. Зазвичай це виконання побітових операцій, які є повільними. На рівні машини вони досить швидкі. Відгалуження ... тепер це повільно.
— Хоган

3
Щоб зробити це більш зрозумілим, якщо ви створите вектор булевих і вкладете в нього 24 булевих, буде потрібно лише 3 байти (3 * 8). Якщо ви помістите інший булевий, він займе ще один байт. Тим не менш, якщо ви натиснете інший булевий, він не займе зайвих байтів, оскільки він використовує "безкоштовні" біти в останньому байті
— Педро Лурейро

так, я також сумніваюсь, що операції з укусом уповільнені :)
— Педро Лурейро

Бітові вектори не створюють виділень розміру біт. вони створюють байтові виділення. Виділити один біт неможливо.
— Джон Дайблінг

1
Читання одного біта в бітовому векторі вимагає трьох операцій: shift і, і ще один зсув знову. Писати два. Тоді як до окремих байтів можна отримати доступ з одним.
— sukru

7

Ще в старі часи, коли мені доводилося ходити до школи в бурхливій хуртовині, в гору обох напрямках, а обід був будь-якою твариною, яку ми могли б відшукати в лісі за школою та вбити голими руками, у комп’ютерів було набагато менше пам’яті, ніж сьогодні. Перший комп'ютер, який я коли-небудь використовував, мав 6К ОЗУ. Не 6 мегабайт, не 6 гігабайт, 6 кілобайт. У цьому середовищі було багато сенсу упакувати якомога більше булів в інт, і ми могли б регулярно використовувати операції, щоб вивезти їх і помістити.

Сьогодні, коли люди знущаються з вас за те, що ви маєте лише 1 ГБ оперативної пам’яті, і єдине місце, де ви могли б знайти жорсткий диск із меншими за 200 ГБ, - це антикварний магазин, просто не варто клопотати, щоб пакувати біти.


За винятком випадків, коли стосується прапорів. Такі речі, як встановлення кількох варіантів на щось ... наприклад. 00000001 + 00000100 = 00000101.
— Армстронгст

@Atomix: Я майже ніколи цього не роблю. Якщо мені потрібні два прапори, я створюю два булевих поля. Раніше я писав код, куди я би упакував такі прапори, а потім писав "якщо прапори & 0x110! = 0 тоді" або подібне, але це загадковим чином, і в ці дні я зазвичай роблю окремі поля і пишу "якщо fooFlag || barFlag "замість цього. Я б не виключав можливості випадків, коли упакувати такі прапорці чомусь краще, але більше не потрібно економити пам’ять, як це було раніше.
— Джей

2
Насправді, цілком варто ваших клопотів з упаковкою бітів, якщо ви хочете, щоб ваше обчислення було швидким - на той великий обсяг даних, який ви зберігаєте в пам'яті. Упаковка булевих файлів не тільки для меншого зберігання - це означає, що ви можете прочитати булеві вхідні масиви в 8 разів швидше (з точки зору пропускної здатності), коли вони розпаковуються, і це часто досить важливо. Також ви можете використовувати бітові операції, як popc (кількість населення), що прискорює вашу роботу над самим процесором.
— einpoklum

2
По-справжньому величезна кількість булевих - це те, з чим ви працюєте щодня, якщо ви робите: СУБД, машинне навчання, наукові симуляції та ще безліч інших речей. І - просто працювати над ними означає їх копіювання - з пам'яті в кеш. Мільйон булів - це нічого, думаю мільярди.
— einpoklum

1
@PeterCordes Так, якщо б у мене був набір булей, які були логічно "тією самою ідеєю", щоб я в певному сенсі вважав їх "масивом", і якщо я збираюся їх маскувати чи фільтрувати або інакше виконайте побізні операції над ними, тоді упаковка їх у байти може мати сенс. Як я вже говорив раніше, мені важко думати про останній раз, коли я працював над додатком, де застосовувалися ці умови, але ви даєте пару хороших прикладів, і я впевнений, що з невеликою уявою можна було б придумати інших.
— Джей

6

Ви можете використовувати бітові поля для отримання цілих чисел нижчого розміру.

struct X
{
    int   val:4;   // 4 bit int.
};

Хоча він зазвичай використовується для нанесення структур на точні шаблони бітових апаратних очікувань:

struct SomThing   // 1 byte value (on a system where 8 bits is a byte
{
    int   p1:4;   // 4 bit field
    int   p2:3;   // 3 bit field
    int   p3:1;   // 1 bit
};

6

У вас можуть бути 1-бітні булі та 4 та 2-бітні вставки. Але це призвело б до отримання дивного набору інструкцій без підвищення продуктивності, оскільки це неприродний спосіб дивитися на архітектуру. Насправді має сенс "витрачати" більшу частину байти, а не намагатися відновити невикористані дані.

На моєму досвіді єдиний додаток, який турбує запакувати кілька булів в один байт, - це сервер Sql.


6

Тому що байт - це найменша адресна одиниця в мові.

Але ви можете змусити bool взяти 1 біт, наприклад, якщо у вас є купа, наприклад. у структурі, як це:

struct A
{
  bool a:1, b:1, c:1, d:1, e:1;
};

2

boolможе бути одним байтом - найменшим адресованим розміром процесора, або може бути більшим. Це не незвично, щоб це boolбуло розміром intдля виконання. Якщо для конкретних цілей (скажімо, апаратного моделювання) вам потрібен тип з N бітами, ви можете знайти для цього бібліотеку (наприклад, бібліотека GBL має BitSet<N>клас). Якщо ви переймаєтесь розміром bool(у вас, мабуть, великий контейнер,), ви можете запакувати біти самостійно або використовувати це, std::vector<bool>що зробить це за вас (будьте обережні з останнім, оскільки він не відповідає вимогам контейнера).


2

Подумайте, як би ви реалізували це на рівні емулятора ...

bool a[10] = {false};

bool &rbool = a[3];
bool *pbool = a + 3;

assert(pbool == &rbool);
rbool = true;
assert(*pbool);
*pbool = false;
assert(!rbool);

2

Тому що загалом процесор виділяє пам'ять з 1 байтом як основну одиницю, хоча деякі процесори, такі як MIPS, використовують 4-байтове слово.

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


1
Я вірю, що навіть процесор MIPS надасть вам доступ до окремого байту, хоча передбачено покарання за продуктивність.
— Пол Томблін

@Paul: Так, ти маєш рацію, але загалом слово-специфічні lw/ swнабагато ширше використовуються.
— Райан Лі

Не знаєте про MIPS, але архітектура IA-64 дозволяє отримати доступ лише на 64-бітних кордонах.
— Гена Бушуєва

0

Байт - це менша одиниця зберігання цифрових даних комп'ютера. У комп'ютері оперативна пам’ять має мільйони байтів, і кожен з них має адресу. Якби у нього була адреса для кожного біта, комп'ютер міг би керувати у 8 разів менше оперативної пам’яті, ніж те, що може.

Більше інформації: Вікіпедія


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