Bool сколько памяти занимает

Обновлено: 06.07.2024

У меня есть две структуры с массивами байтов и булевых:

И следующий код:

Это дает мне следующий результат:

Кажется, что boolean занимает 4 байта памяти. В идеале a boolean будет принимать только один бит ( false или true , 0 или 1 и т.д.).

Что здесь происходит? Действительно ли тип boolean настолько неэффективен?

Тип bool имеет клетчатую историю со многими несовместимыми выборами между языковыми режимами. Это началось с исторического выбора дизайна, сделанного Деннисом Ритчи, парнем, который изобрел C-язык. У него не было типа bool, альтернативой было int, где значение 0 представляет значение false, а любое другое значение считается истинным.

Независимо от того, что вы делаете, ваше объявление структуры должно соответствовать совпадению с выбором времени выполнения, выполняемым на языке, с которым вы взаимодействуете. Как уже отмечалось, BOOL для winapi, но большинство реализаций на С++ выбрали байты, большинство COM Automation interop использует VARIANT_BOOL, который является коротким.

Другими словами, вы всегда должны маршировать структуру во время выполнения, чтобы приглушить макет. В это время выполняется преобразование из внутренней компоновки в макет interop. Это может быть очень быстрым, если макет идентичен, медленный, когда поля необходимо переустановить, поскольку для этого всегда требуется создать копию структуры. Технический термин для этого является blittable, передача blittable struct в собственный код выполняется быстро, потому что маркерщик pinvoke может просто передать указатель.

Производительность также является основной причиной того, что bool не является одним битом. Существует несколько процессоров, которые делают бит непосредственно адресуемым, а наименьший - байтом. Требуется дополнительная инструкция, чтобы выловить бит из байта, который не приходит бесплатно. И он никогда не является атомарным.

CLR на самом деле использует возможность того, что макет не может быть распознан, он может оптимизировать макет класса и перенастроить поля, чтобы скрыть его. Итак, скажем, если у вас есть класс с членом bool + int + bool, тогда он будет принимать 1 + (3) + 4 + 1 + (3) байты памяти, (3) является дополнением, в общей сложности 12 байт. 50% отходов. Автоматическая компоновка перестраивается до 1 + 1 + (2) + 4 = 8 байтов. Только класс имеет автоматическую компоновку, по умолчанию структуры имеют последовательный макет.

Тем не менее, эта аналогия не совсем подходит к программированию, так как переменные могут занимать больше 1 байта памяти. Следовательно, одна переменная может использовать 2, 4 или даже 8 последовательных адресов. Объем памяти, который использует переменная, зависит от типа данных этой переменной. Так как мы, как правило, получаем доступ к памяти через имена переменных, а не через адреса памяти, то компилятор может скрывать от нас все детали работы с переменными разных размеров.

Есть несколько причин по которым полезно знать, сколько памяти занимает определенная переменная/тип данных.

Во-первых, чем больше она занимает, тем больше информации сможет хранить. Так как каждый бит содержит либо 0 , либо 1 , то 1 бит может иметь 2 возможных значения.

2 бита могут иметь 4 возможных значения:

бит 0 бит 1
0 0
0 1
1 0
1 1

3 бита могут иметь 8 возможных значений:

бит 0 бит 1 бит 2
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

По сути, переменная с n-ным количеством бит может иметь 2 n возможных значений. Поскольку байт состоит из 8 бит, то он может иметь 2 8 (256) возможных значений.

Размер переменной накладывает ограничения на количество информации, которую она может хранить. Следовательно, переменные, которые используют больше байт, могут хранить более широкий диапазон значений.

Размер основных типов данных в C++

Язык C++ гарантирует только их минимальный размер:

Тип Минимальный размер
Логический тип данных bool 1 байт
Символьный тип данных char 1 байт
wchar_t 1 байт
char16_t 2 байта
char32_t 4 байта
Целочисленный тип данных short 2 байта
int 2 байта
long 4 байта
long long 8 байт
Тип данных с плавающей запятой float 4 байта
double 8 байт
long double 8 байт

Фактический размер переменных может отличаться на разных компьютерах, поэтому для его определения используют оператор sizeof.

Оператор sizeof — это унарный оператор, который вычисляет и возвращает размер определенной переменной или определенного типа данных в байтах. Вы можете скомпилировать и запустить следующую программу, чтобы выяснить, сколько занимают разные типы данных на вашем компьютере:

Для всех примитивных типов данных, кроме типа boolean , в Java однозначно определен размер.

Размер типа boolean , насколько я понимаю, зависит от реализации конкретной виртуальной машины.

Вопрос: почему для типа boolean однозначно не определили размер?

Встречный вопрос. А с какими целями это, по-вашему, может быть надо? Полагаю, что ответ "определять размер однозначно было просто незачем" вас не устроит. Потому что boolean - 1 бит. А адресовать один бит нельзя. А количество бит/байт которые можно адресовать (читай, минимальный размер памяти, который можно прочитать) в теории зависит от реальной машины, на которой исполняется java. Думаю причина в этом.

Если поведение однозначно определено, всё остальное вторично.

Тип boolean прекрасно определяется множеством своих допустимых значений. Математически оно ограничивает минимальный размер значения одним битом.

Но использовать именно один бит (и ни битом более) эффективно далеко не всегда, поскольку на популярных архитектурах нельзя адресовать отдельные биты. А потому значения отдельных boolean 'ов нельзя быстро сохранить в отдельные биты оперативной памяти — необходимо использовать комбинацию побитовых операций, что почти наверняка будет медленнее, чем запись целого отдельного регистра в оперативную память (размер которого может быть различным на разных платформах!).

Но при этом, к примеру, я вполне себе представляю, как на x86 компилятор может использовать в нативном коде в качестве какого-нибудь конкретного boolean -значения один бит регистра флагов, при условии, что это значение никогда не попадает в оперативную память (отдельно от других). Поэтому любые ограничения на размер более одного бита тоже могут потенциально мешать.

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

может ли кто-нибудь сказать размер бита boolean в Java?

Это зависит от виртуальной машины.

Это зависит от виртуальной машины, но легко адаптировать код аналогичный вопрос о байтах в Java:

чтобы повторить, это зависит от виртуальной машины, но на моем ноутбуке Windows под управлением Sun JDK build 1.6.0_11 я получил следующие результаты:

это говорит о том, что булевы могут быть в основном упакованы в байт каждый JVM Sun.

фактическая информация, представленная логическим значением в Java, является одним битом: 1 для true, 0 для false. Однако фактический размер булевой переменной в памяти точно не определяется спецификацией Java. Смотрите примитивные типы данных в Java.

логический тип данных имеет только два возможные значения: true и false. Использовать этот тип данных для простых флагов, которые отслеживание истинных / ложных условий. Эта информация тип представляет один бит информация, но его "размер" не что-то, что точно определено.

на боковой ноте.

Если вы думаете об использовании массива булевых объектов, не используйте вместо этого битовый набор - у него есть некоторые оптимизации производительности (и некоторые хорошие дополнительные методы, позволяющие вам получить следующий бит set/unset).

Я читал, что Java резервирует один байт для boolean тип данных, но он использует только один бит. Однако в документации говорится, что " его "размер" - это не то, что точно определено". см. здесь.

The boolean значения компилируются в int тип данных в JVM. Смотрите здесь.

размер логического значения в java зависит от виртуальной машины. но любой объект Java выравнивается до 8 байт детализации. Логическое имеет 8 байт заголовка, плюс 1 байт полезной нагрузки, в общей сложности 9 байт информации. В JVM затем округляется до следующего значения, кратного 8. Итак, один экземпляр java.ленг.Boolean занимает 16 байт памяти.

это неопределенно; делать такие вещи, как предложил Джон Скит, даст вам приближение на данной платформе, но способ точно узнать для конкретной платформы-использовать профилировщик.

Читайте также: