расположение битовых полей в структуре

Учитывая, что есть некоторые несвязанные флаги (sta_scan, search), которые определены как битовые поля в структуре, как показано ниже. Имеет ли значение место, где объявлены эти флаги (с точки зрения сохранения памяти)?

struct sta_all {
    char name[16];
    unsigned int sta_scan:1;
    ...
    int interval;
    unsigned int search:1;
}

person artm    schedule 01.09.2016    source источник
comment
Каждому из этих битовых полей, вероятно, будет выделено столько же места, сколько базовому типу (unsigned int), и будет использоваться 1 из 32 (16, 64, …) битов в этой единице хранения. Если вы решите использовать битовые поля, вы должны убедиться, что все битовые поля сгруппированы вместе; это сведет к минимуму потраченное впустую пространство. Вы должны подумать о том, будет ли bool (из <stdbool.h> или _Bool) служить вашим целям также или лучше. Многие детали битовых полей определяются реализацией, но в контексте структуры у компилятора нет свободы перемещать битовые поля.   -  person Jonathan Leffler    schedule 01.09.2016
comment
компиляторам не разрешено переупорядочивать элементы структуры, поэтому вам нужно сделать это самостоятельно, если вы не включите некоторые параметры компилятора   -  person phuclv    schedule 01.09.2016
comment
artM хороший вопрос, я редактирую свой ответ, так как вчера вечером, вместо того, чтобы считать овец в своей постели, я считал биты, надеюсь, вы найдете это полезным! :)   -  person gsamaras    schedule 01.09.2016
comment
@gsamaras круто. Исходная структура на самом деле намного больше, и я действительно видел много несвязанных флагов, подобных этим, разбросанных повсюду. Поэтому мне было интересно, действительно ли эти разбросанные битовые поля будут иметь значение, или вместо этого мы можем просто использовать обычный int.   -  person artm    schedule 02.09.2016


Ответы (2)


Да, но не всегда.


Проверьте этот пример:

#include <stdio.h>
#include <string.h>

struct {
    char name[16];
    unsigned int sta_scan:1;
    int interval;
    unsigned int search:1;
} sta_all;

int main( ) {

   sta_all.interval = 4;
   printf( "Sizeof(sta_all) : %zu\n", sizeof(sta_all) );

   return 0;
}

Выход:

Sizeof(sta_all) : 28

а также:

#include <stdio.h>
#include <string.h>

struct {
    char name[16];
    unsigned int sta_scan:1;
    unsigned int search:1;
    int interval;
} sta_all;

int main( ) {

   sta_all.interval = 4;
   printf( "Sizeof(sta_all) : %zu\n", sizeof(sta_all) );

   return 0;
}

Выход:

Sizeof(sta_all) : 24

Это происходит из-за padding, на моей платформе.

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

Примечание. Приведенный выше пример подтверждает то, что Джонатан Леффлер упомянул в этом комментарий:

Каждому из этих битовых полей, вероятно, будет выделено столько же места, сколько базовому типу (unsigned int), и будет использоваться 1 из 32 (16, 64, …) битов в этой единице хранения. Если вы решите использовать битовые поля, вы должны убедиться, что все битовые поля сгруппированы вместе; это сведет к минимуму потраченное впустую пространство. [...]. В контексте структуры компилятор не может свободно перемещать битовые поля.

.. что идеально гармонирует со связанным ответом, поскольку компилятору придется добавить меньше char gap_{i}[3];, когда мы кластеризуем битовые поля, тем самым сводя к минимуму размер структуры!


Стоит ли оно того?

ИМХО не очень... :)

person gsamaras    schedule 01.09.2016
comment
Почему вы поместили огромные поля, которые ОП не должен делать, чтобы относительная разница казалась искусственно маленькой? - person R.. GitHub STOP HELPING ICE; 01.09.2016
comment
@R.. просто для удовольствия. Но поведение, конечно, не изменится. Проверьте мое обновление, вам нравится мой ответ сейчас? :) - person gsamaras; 01.09.2016
comment
Я бы хотел, чтобы было лучше, если бы это было 24 против 28 (без добавления глупых поплавков). - person R.. GitHub STOP HELPING ICE; 01.09.2016

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

person alex.forencich    schedule 01.09.2016
comment
Вы не можете принудительно не заполнять битовое поле. - person R.. GitHub STOP HELPING ICE; 01.09.2016