C ++: почему bool имеет длину 8 бит?

132

В C ++ мне интересно, почему тип bool имеет длину 8 бит (в моей системе), где только одного бита достаточно для хранения логического значения?

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

Или это всего лишь одна из этих «исторических» причин?

Жером
источник
9
В моей системе bool не 8-битный. Это 4 байта, то же самое, что и int.
Брайан Нил,
21
в прошлый раз, когда кто-то подумал, о чем вы думаете, мы закончили с std :: vector <bool>, самой ненавистной «функцией» stl за всю историю =)
Виктор Сер
1
jldupont, я думаю, вы меня неправильно поняли. Я просил систему, где sizeof(bool)будет 4. Могу поклясться, что у msvc были 32-битные логические значения, но я просто попробовал, но этого не произошло.
avakar
7
Честно говоря, проблема vector<bool>не в том, что он пытается быть умным и упаковывать bools в биты, а в том, что он пытается это сделать и замаскировать себя под контейнер STL . Обычный битовый набор был бы хорош, если бы он также не претендовал на роль контейнера STL.
jalf
2
@avakar - вы можете спутать boolтип данных C ++ с BOOLтипом Windows, для которого задан тип long. Итак sizeof(bool) != sizeof(BOOL), что, я уверен, вызывает большую путаницу (и, вероятно, изрядное количество ошибок). Тем более что в Windows есть booleanи BOOLEANtypedef, которые являются псевдонимами для unsigned char. Также обратите внимание, что, хотя обычно boolэто 1 байт, в стандарте C ++ есть примечание, в котором конкретно указывается, что он sizeof(bool)может быть больше.
Майкл Берр

Ответы:

219

Потому что каждый тип данных C ++ должен быть адресуемым.

Как бы вы создали указатель на один бит? Ты не можешь Но вы можете создать указатель на байт. Таким образом, логическое значение в C ++ обычно имеет размер в байтах. (Он также может быть больше. Это зависит от реализации. Главное, чтобы он был адресуемым, поэтому тип данных C ++ не может быть меньше байта)

jalf
источник
7
«Байтовая» адресация - это архитектурный выбор (уровень hw): вполне можно разработать систему с другой «единицей адресации». Для обычных процессоров обращение к «байту» в любом случае приводит к извлечению из внешней памяти более «байта»: это связано с соображениями эффективности.
jldupont
8
Да, это выбор оборудования, и если оборудование позволяет это, размер bool может измениться. Но OP спросил, почему bool имеет ширину 8 бит, а в системах, где это так, обычно это потому, что ЦП может адресовать только 8-битные байты.
jalf
2
@jldupont: есть несколько систем, в которых адреса указателей более мелкие, чем байты (раньше я программировал на старом TI TMS34010 / 20, который использует побитовые указатели), но они ЧРЕЗМЕРНО редки.
Майкл Кон,
1
Не уверен, что вы имеете в виду. Каждый объект должен быть адресуемым, то есть должна иметься возможность получить адрес объекта. Объекту не обязательно хранить собственный адрес. Ширина char обычно составляет 8 бит, что достаточно для хранения любого из 256 символов, но каждый символ также имеет адрес, определяемый тем, где он находится в памяти. Вот почему вы можете создать указатель на char.
jalf
88
Если можно, я приведу хитроумную аналогию: в моем здании восемь этажей, но почтовое отделение не признает, что это разные адреса. Поэтому, если я хочу получить адрес только для себя, то мне придется арендовать все здание, даже если я умещаюсь на одном этаже. Я не использую остальные семь этажей для «хранения адреса», я просто вынужден тратить их зря из-за правила почтового отделения, согласно которому адреса относятся к зданиям, а не к этажам. Объекты C ++ должны иметь собственный адрес - никаких почтовых комнат для сортировки почты после доставки ;-)
Стив Джессоп,
39

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

Стивен Роантри
источник
1
Не всегда. Например, микроконтроллер 8051 имеет 16 байтов
адресов с
20

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

Доступ к памяти всегда осуществляется «порциями» (несколько слов, это для эффективности на аппаратном уровне , транзакции шины): логический бит не может быть адресован «в одиночку» в большинстве систем ЦП. Конечно, после того, как данные содержатся в регистре , часто существуют специальные инструкции для независимого управления битами.

По этой причине довольно часто используются методы «битовой упаковки» для повышения эффективности использования «логических» базовых типов данных. Такой метод, как enum(в C) с кодированием степени 2, является хорошим примером. Такой же прием можно найти в большинстве языков.

Обновлено : благодаря отличному обсуждению, мое внимание было обращено на то, что sizeof(char)==1по определению в C ++. Следовательно, адресация «логического» типа данных в значительной степени привязана к наименьшей единице адресуемой памяти (подтверждает мою точку зрения).

jldupont
источник
Из всех комментариев, которые вы оставили по этому поводу, впечатляет, что вы упустили самую важную часть ответа: boolтип следует за наименьшей единицей выделяемой памяти, потому что C ++ требует, чтобы была возможность создавать указатели на него . Без этого требования a boolможно было бы представить как отдельный бит даже на современных машинах с байтовой адресацией.
jalf
1
хммм ... Я мог бы создать архитектуру ЦП, в которой бит может быть адресуем ... Я мог бы даже написать для него компилятор и т.д. Я мог бы иметь особую область памяти (или что-то еще), которая была бы «адресуемой по битам». Это не невозможно ни при каких обстоятельствах.
jldupont
2
Да, и в этой системе логическое значение можно сделать одним битом. Но OP не спрашивал «почему ширина bool 8 бит на гипотетическом процессоре jlduponts». Он спросил о текущих, обычных, повседневных процессорах, и о них это потому, что они имеют байтовую адресацию.
jalf
4
sizeof (char) == 1 на определение в C ++, поэтому то, что ваше оборудование может или не может делать, не имеет значения. У вас не может быть sizeof (bool) <sizeof (char). BTW C ++ определен таким образом, что у вас может быть «толстый» указатель для адресации некоторой подъединицы того, что оборудование может адресовать, если не удобно иметь char наименьшую аппаратную адресуемую единицу. Это использовалось, по крайней мере, в некоторых компиляторах C для старых адресных архитектур.
AProgrammer
@AProgrammer:: sizeof(char)==1 definitionэто лучший контраргумент моей аргументации. Спасибо!
jldupont
6

Ответы о том, что 8-битный наименьший объем адресуемой памяти, верны. Однако некоторые языки могут в некотором смысле использовать 1-бит для логических значений. Кажется, я помню, как Паскаль реализовывал наборы как битовые строки. То есть для следующего набора:

{1, 2, 5, 7}

У вас может быть это в памяти:

01100101

Конечно, вы можете сделать что-то подобное на C / C ++, если хотите. (Если вы отслеживаете кучу логических значений, это может иметь смысл, но это действительно зависит от ситуации.)

Бенджамин Оукс
источник
8
Фактически, C ++ делает это с помощью специализированного вектора-контейнера <bool> - это обычно рассматривается как катастрофа.
C ++ также делает это с «битовыми полями», унаследованными от C. При объявлении переменной-члена структуры / класса вы можете объявить количество битов, используемых для хранения значения (например, «короткое поле без знака: 3»).
@ Нил: почему это обычно воспринимается как катастрофа? Это проблема производительности?
Жером,
2
@Jerome: Это потому, что, поскольку бит не адресуем, он не может вести себя так, как обычный vector. На самом деле это не контейнер типа STL, потому что на его поведение накладываются ограничения. Что еще хуже, это вызывает проблемы с кем-то, у кого есть bools и кто хочет сделать vectorиз них. Это удивительное поведение, а это не то, что вы хотите от языка.
Дэвид Торнли
1
@jldupont - достаточно один раз заявить об этом. И C ++ не дает никаких гарантий, что биты адресуются (скорее, наоборот), независимо от того, на что способно оборудование.
1

Я знаю, что это старый, но я подумал, что брошу свои 2 цента.

Если вы ограничите логическое значение или тип данных одним битом, ваше приложение подвергнется риску нарушения памяти. Как вы обрабатываете статистику ошибок в памяти, длина которой составляет всего один бит?

Я пошел на собеседование, и одно из заявлений, которые руководитель программы сказал мне, было: «Когда мы отправляем сигнал для запуска ракеты, мы просто отправляем простой бит на выключение по беспроводной сети. Отправка одного бита выполняется очень быстро, и мы нужно, чтобы сигнал был как можно быстрее ".

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

Cire
источник
Задайте новый вопрос , не размещайте свой вопрос как ответ на другие вопросы.
Игорь Еросимич
6
Я думаю, что вопрос, содержащийся в этом «ответе», на самом деле риторический, то есть причина, по которой мы не реализуем логические значения как один бит, заключается в том, что отдельный бит не может обрабатывать статистику ошибок.
Стивен Холт
1
@StephenHolt, но причина не в этом, и этот ответ не имеет никакого смысла.
doc
1
...какие? Я не знаю, что вы имеете в виду под «статистикой ошибок», будь то CRC и т.п., или представления ловушек. Но в любом случае даже более крупные типы не используют свои дополнительные, «запасные» биты для «статистики ошибок», поскольку все кодировщики, кроме экстремальных, справедливо полагают, что их оборудование может обрабатывать обнаружение / исправление ошибок до того, как их код когда-либо считывает память, поэтому они не нужно тратить свое время на дополнение каждой переменной проверочной информацией или чем-то еще. Не поэтому boolиспользуется 8 бит на машине OP и 32 на моей, так как эти 7 или 31 бит определенно не используются для какой-либо «статистики ошибок». В этом нет никакого смысла
underscore_d
1

Некоторые встроенные компиляторы имеют тип int1, который используется для битовой упаковки логических флагов (например, серия компиляторов C CCS для микропроцессоров Microchip). Для установки, очистки и тестирования этих переменных используются инструкции на уровне битов с одной инструкцией, но компилятор не разрешает никаких других операций (например, получение адреса переменной) по причинам, указанным в других ответах.

EBlake
источник