Размер битового поля не так, как ожидалось, почему?

Почему это битовое поле имеет размер 4? Есть ли у меня способ сделать это размером 2 (как очевидно, в коде ниже), или это невозможно сделать чисто?

struct S
{
    unsigned short x : 15;
    bool a : 1;
};

int main() { return sizeof(S); }
0
nl ja de
@KBart: почему размер word влияет на выравнивание unsigned short , который является полусловом? struct T {без знака short s1, s2; }; , конечно, не имеет выравнивания 4, насколько я знаю! Кроме того, я должен отметить, что добавление #pragma pack (1) уменьшает размер до 3, но не 2.
добавлено автор Mehrdad, источник
@KBart: Я на 95% уверен, что вы ошибаетесь ... исправьте меня, если я ошибаюсь, но я считаю, что выравнивание структуры (которая определяет внутреннее наполнение, созданное внутренне), является наибольшим выравниванием любого из ее членов, и никак не зависит от размера слова машины.
добавлено автор Mehrdad, источник
@Krishna: На каком компиляторе, конечно, не Visual Studio, не так ли? o.o
добавлено автор Mehrdad, источник
@JoachimPileborg: Хм, по вашей логике, тогда, как вы думаете, будет ли размер struct U {bool a: 1; bool b: 1; } ? Один байт или два байта?
добавлено автор Mehrdad, источник
@KBart: Я посмотрю, но я полностью понимаю, что он зависит от системы. Я пытаюсь понять результаты, которые я получаю.
добавлено автор Mehrdad, источник
@KBart: Да, я знаю, что такое выравнивание и упаковка, но проблема не в том, что вы думаете. Посмотрите на ответ Аникет ниже.
добавлено автор Mehrdad, источник
@KBart: Эх, я также видел, как другие жалуются на избыточность ... Я не знаю, в какую песню танцевать, но в этом случае я думаю, что оставлю это как есть.
добавлено автор Mehrdad, источник
@KBart: Вот почему никто не говорил о стандарте для начала, я не знаю, почему все говорят о стандарте внезапно. В целом речь шла о Visual C ++.
добавлено автор Mehrdad, источник
@Mehrdad 2 здесь, в моем gcc. Вы знаете ... MSVC - это компилятор дьявола, я его ненавижу!
добавлено автор André Puel, источник
#pragma pack (1) прокладки каждого члена до ближайшего байта, и у вас есть два члена, поэтому размер становится три (два для первого и второго для второго) ,
добавлено автор Some programmer dude, источник
Я получаю результат как 2!
добавлено автор Krishnachandra Sharma, источник
@Mehrdad, добавьте ссылку компилятора на заголовок, так как тег легко пропустить, как и должно быть, я сделал ..;)
добавлено автор KBart, источник
@Mehrdad Я только объяснил первую часть вашего вопроса (почему он имеет размер 4), поэтому я не опубликовал его как полный ответ. Вторая часть (упаковка) зависит от вашего компилятора, поскольку интерпретация #pragma s не является частью стандарта.
добавлено автор KBart, источник
@Mehrdad, выглядит как обсуждение произошло здесь некоторое время назад, посмотрите, есть также отличные ответы, включая примеры.
добавлено автор KBart, источник
@Mehrdad см. здесь для примера. На самом деле все эти связанные с памятью вещи очень надежны для системы, поэтому неудивительно, что вы получаете разные результаты.
добавлено автор KBart, источник
он не влияет на размер unsigned short, он добавляет 2 байта для заполнения, как я заявил в моем отредактированном комментарии.
добавлено автор KBart, источник
Я полагаю, что word размер 4 байта (32 бит) в вашей системе, а структуры обычно выравниваются по слову, поэтому для заполнения добавляются 2 дополнительных байта.
добавлено автор KBart, источник

1 ответы

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

в VC ++ это #pragma pack

Также, чтобы получить размер 2, вы должны сделать это:

#pragma pack(1)
struct s{
  unsigned short s1: 15;
  unsigned short b1: 1;
};

С #pragma pack в вашем коде:

struct S
{
    unsigned short x : 15;
    bool a : 1;
};

Гипотетическая схема памяти:

----------------------
+ 1 | 2 | 3 | 4 | 5 | ..
+   x   | a |
+---------------------

Следовательно, он занимает 3 байта

изменив bool a на unsigned short a , вы получите следующее:

-------------------------
+ 1 | 2 | 3 | 4 | 5| ..
+   x |a|
-------------------------

Которая занимает всего 2 байта.

Компилятор решает, что, поскольку второй короткий принимает только 1 бит, можно просто сжать структуру в 2 байта. Но если используется элемент структуры другого типа (например, bool в вашей реализации S ), компилятор думает, так как типы разные, он не может фактически сжать 1 бит в unsigned short (потому что он пересекает границу типа - к сожалению, реализация определена). Следовательно, вы получаете 3 байты для sizeof() вместо 2.

4
добавлено
@Aniket: Спасибо за редактирование, но вы продолжаете говорить «компилятор думает ...» , который просит меня спросить: why Неужели это так? Это произвольное решение, случайное поведение или есть причина? Тот факт, что он «что-то» что-то думает и принимает решение, теперь достаточно очевиден, что мы знаем, что происходит, но объяснение почему - это то, что я не понимаю.
добавлено автор Mehrdad, источник
@JamesKanze: Так вы говорите, что Visual C ++ сделал произвольное решение, «если тип меняется, а затем« pad »?
добавлено автор Mehrdad, источник
@Aniket: Вы просто повторяете то, что, очевидно, происходит, но я спрашиваю почему делает это?
добавлено автор Mehrdad, источник
+1, потому что он работает, но not из-за упомянутой вами прагмы! Кажется, это из-за типа ... но почему меняется переменная bool на unsigned short ?
добавлено автор Mehrdad, источник
@Aniket. Если вы не можете назначить bool для unsigned short . Оба являются интегральными типами и свободно конвертируются.
добавлено автор James Kanze, источник
@Mehrdad Более или менее. Практически говоря, все решения относительно того, как битовые поля макета более или менее произвольны.
добавлено автор James Kanze, источник
@Aniket На самом деле, нет причин, кроме того, что решили разработчики компилятора. Все это очень произвольно, и реализация определена.
добавлено автор James Kanze, источник
Только одна причина: bool будет принимать дополнительный байт за 1 бит. с unsigned short, он попытается упаковать все в короткий.
добавлено автор Aniket Inge, источник
@JamesKanze, как я сказал, его реализация определена. Его нестандартный стандарт C ++ и C ++ не позволяет создавать не проложенные структуры AFAIR
добавлено автор Aniket Inge, источник
@Mehrdad да, позвольте мне изменить мой ответ, чтобы рассказать вам, почему
добавлено автор Aniket Inge, источник
pro.cxx
pro.cxx
3 049 участник(ов)

C/C++ chat 0. Простые вопросы, лабы и о IDE — в чат новичков @supapro 1. Не хамим, не переходим на личности, не вбрасываем утверждения без доказательств 2. No Ads, offtop, flood Объявления о вакансиях и евенты - в лс @AlexFails https://t.me/ProCxx/259155

supapro.cxx
supapro.cxx
1 925 участник(ов)

Чат для тех, кто немного знает C++, простые вопросы по реализации, синтаксису и ide – сюда, а для другого есть: /Главный чат по серьезным вопросам — @ProCxx /Чат по обсуждению всего — @fludpac

C++ Russia
C++ Russia
384 участник(ов)

Сообщество разработчиков C++ в Telegram.

cxx.Дискуссионная
cxx.Дискуссионная
298 участник(ов)

это не двач, общайтесь вежливо; разговор на почти любые темы; Не согласны с баном? В лс @AlexFails, @ivario

C++ для маленьких и тупых
C++ для маленьких и тупых
105 участник(ов)

Лоу левел (по среднему IQ участников) чатик ExtremeCode @extremecode Флудилка @extremecode_rest