Тип bool має картату історію з багатьма несумісними варіантами між мовними режимами. Це почалося з вибору історичного дизайну, який зробив Денніс Річі, хлопець, який винайшов мову С. У нього не було типу bool , альтернативою був int, коли значення 0 являє собою хибне, а будь-яке інше значення вважається істинним .
Цей вибір був перенесений у Winapi, головна причина використання pinvoke, він має typedef, для BOOL
якого є псевдонімом для ключового слова int компілятора C. Якщо ви не застосуєте явний атрибут [MarshalAs], тоді C # bool перетворюється на BOOL, таким чином, створюючи поле, довжиною 4 байти.
Що б ви не робили, ваша структура декларації повинна відповідати вибору часу виконання на мові, з якою ви взаємодієте. Як зазначалося, BOOL для winapi, але більшість C ++ реалізацій обрали байт , більшість інтеропів COM Automation використовує VARIANT_BOOL, що є коротким .
Фактичний розмір C # bool
становить один байт. Сильна проектна мета CLR полягає в тому, що ви не можете цього дізнатися. Макет - це деталь реалізації, який занадто сильно залежить від процесора. Процесори дуже вибагливі до змінних типів та вирівнювання, неправильний вибір може істотно вплинути на продуктивність та призвести до помилок виконання. Роблячи макет нерозкритим, .NET може забезпечити систему універсального типу, яка не залежить від реальної реалізації часу.
Іншими словами, вам завжди потрібно зруйнувати структуру під час виконання, щоб прибити макет. У цей час здійснюється перетворення з внутрішнього макета в макет інтеропа. Це може бути дуже швидким, якщо макет однаковий, повільний, коли поля потрібно переставляти, оскільки це завжди вимагає створення копії структури. Технічний термін для цього є простим , передача структури, що випускається, до нативного коду є швидкою, оскільки маршовий механізм Pinvoke може просто передати покажчик.
Продуктивність також є основною причиною того, що bool - це не один біт. Є небагато процесорів, які роблять біт безпосередньо адресованим, найменша одиниця - байт. Додаткові інструкції потрібно для риби біт з байта, який не спадає безкоштовно. І це ніколи не атомно.
Компілятор C # інакше не соромляться сказати вам, що він займає 1 байт, використовуйте sizeof(bool)
. Це все ще не фантастичний передбачувач, скільки байтів займає поле під час виконання, CLR також потрібно реалізувати модель пам'яті .NET, і він обіцяє, що прості оновлення змінних є атомними . Для цього потрібні правильні вирівнювання змінних у пам'яті, щоб процесор міг оновлювати її за допомогою одного циклу шини пам'яті. Досить часто bool насправді вимагає 4 або 8 байт в пам'яті через це. Додаткові накладки, які були додані для забезпечення правильного вирівнювання наступного члена.
CLR фактично використовує перевагу, що макет не виявляється, він може оптимізувати компонування класу та переупорядкувати поля, щоб мінімізація прокладки була мінімізована. Так, скажімо, якщо у вас є клас з bool + int + bool, то знадобиться 1 + (3) + 4 + 1 + (3) байти пам'яті, (3) - це прокладка, загалом 12 байт 50% відходів. Автоматичне розташування переставляє на 1 + 1 + (2) + 4 = 8 байт. Тільки клас має автоматичний макет, структури мають за замовчуванням послідовний макет.
Більш м'яко, bool може вимагати аж 32 байти в програмі C ++, складеній із сучасним компілятором C ++, який підтримує набір інструкцій AVX. Якщо вимога вирівнювання має 32 байти, змінна bool може закінчуватися 31 байтом прокладки. Крім того, основна причина, чому .NET тремтіння не видає інструкції SIMD, якщо явно не завернуто, він не може отримати гарантію вирівнювання.