Почему логическое значение потребляет больше памяти, чем char?

StackOverflow https://stackoverflow.com/questions/204256

  •  03-07-2019
  •  | 
  •  

Вопрос

Почему логическое значение занимает 4 байта, а char — 2 байта в платформе .NET?Логическое значение должно занимать 1 бит или, по крайней мере, быть меньше символа.

Это было полезно?

Решение

Это вопрос выравнивания памяти.4-байтовые переменные работают быстрее, чем 2-байтовые.Именно по этой причине вам следует использовать int вместо byte или сокращение для счетчиков и тому подобного.

Вам следует использовать 2-байтовые переменные только тогда, когда память важнее скорости.И именно по этой причине char (который в .NET представляет собой Unicode) занимает два байта вместо четырех.

Другие советы

О boolean

Большинство других ответов ошибаются: выравнивание и скорость - вот почему программист должен придерживаться int для счетчиков циклов, а не почему компилятор может сделать байт шириной 4 байта.Все ваши рассуждения, по сути, применимы как к байтовым и коротким, так и к логическим значениям.

По крайней мере, в C# bool (или System.Boolean) представляет собой встроенную структуру шириной 1 байт, которую можно автоматически упаковать, поэтому у вас есть объект (для представления которого требуется как минимум два слова памяти, т.е.8/16 байт в 32/64-битной среде соответственно) с полем (по крайней мере, один байт) плюс одно слово памяти, указывающее на него, т.е.всего не менее 13/25 байт.

Это действительно первая запись Google о «примитивных типах C#».http://msdn.microsoft.com/en-us/library/ms228360(VS.80).aspx

Также цитируемая ссылка (http://geekswithblogs.net/cwilliams/archive/2005/09/18/54271.aspx) также утверждает, что логическое значение по стандарту CLI занимает 1 байт.

На самом деле, однако, единственное место, где это видно, - это массивы логических значений: n логических значений занимают n байтов.В остальных случаях одно логическое значение может занимать 4 байта.

  • Внутри структуры большинство сред выполнения (также в Java) выравнивают все поля по границе в 4 байта для повышения производительности.JVM Monty для встраиваемых устройств более мудра — я думаю, она оптимально переупорядочивает поля.
    • В локальном стеке фреймов/операндов интерпретатора в большинстве реализаций для повышения производительности одна запись стека имеет ширину в одно слово памяти (и, возможно, в .NET она должна быть 64-битной шириной для поддержки двойных и длинных значений, что в .NET использует только одну запись стека вместо двух в Java).Вместо этого JIT-компилятор может использовать 1 байт для логических локальных значений, сохраняя при этом выравнивание других переменных путем изменения порядка полей без ущерба для производительности, если дополнительные накладные расходы того стоят.

О char

char представляют собой два байта, поскольку, когда требуется поддержка интернационализации, самым безопасным вариантом является внутреннее использование двухбайтовых символов.Это не связано напрямую с выбором поддержки Unicode, а с выбором придерживаться UTF-16 и базовой многоязычной плоскости.В Java и C# вы всегда можете предполагать, что один логический символ помещается в переменную типа char.

Это связано с тем, что в 32-битной среде ЦП может обрабатывать 32-битные значения быстрее, чем 8-битные или 16-битные значения, поэтому это компромисс между скоростью и размером.Если вам нужно сэкономить память и у вас большое количество логических значений, просто используйте uints и сохраните ваши логические значения как биты по 4 байта. uintс.Ширина символов составляет 2 байта, поскольку они хранят 16-битные символы Юникода.

Несмотря на незначительную разницу в хранении в памяти, использование логического значения для значений true/false (да/нет) важно для разработчиков (включая вас самих, когда вам придется вернуться к коду год спустя), поскольку оно более точно отражает ваши намерения.Сделать ваш код более понятным гораздо важнее, чем сэкономить два байта.

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

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

Я нашел это:«На самом деле логическое значение имеет размер 4 байта, а не 2.Причина в том, что CLR поддерживает именно это значение для логических значений.Я думаю, это то, что он делает, потому что 32-битными значениями гораздо эффективнее манипулировать, поэтому компромисс между временем и пространством, в целом, того стоит.Вам следует использовать класс битовых векторов (забудьте, где он находится), если вам нужно склеить кучу битов вместе..."

Это написано Полом Уиком на http://geekswithblogs.net/cwilliams/archive/2005/09/18/54271.aspx

ИМХО, прежде всего вам следует использовать профилировщик, чтобы определить, где у вас проблемы с памятью.

Память имеет значение только в том случае, если у вас большой массив битов, и в этом случае вы можете использовать класс System.Collections.BitArray.

Это потому, что Windows и .Net использовали Юникод (UTF 16) с момента создания в качестве внутреннего набора символов. UTF 16 использует 2 байта на символ или пару 2-байтовых слов на символ, но только если это необходимо, поскольку это кодирование переменной ширины.

«Для символов в базовой многоязычной плоскости (BMP) результирующая кодировка представляет собой одно 16-битное слово.Для символов в других плоскостях результатом кодирования будет пара 16-битных слов.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top