Удобство использования битовых полей - PullRequest
3 голосов
/ 04 мая 2019

Существует много советов, говорящих не об использовании битовых полей, а о том, чтобы выполнять битовую арифметику вручную (например, Когда использовать битовые поля в C? ), поскольку макеты битовых полей определяются реализацией.

Это практически проблема? Я заметил, что SysV ABI для x86-64 , например, определяет, как должны быть расположены битовые поля, поэтому я предполагаю, что использование битовых полей на этой платформе не должно быть проблематичным, даже если я смешиваю объектный код, сгенерированный разные компиляторы.

Аналогично ли стандартизированы битовые поля на других платформах? (В основном меня интересуют Linux (SysV ABI), MacOs и CygWin.)

Ответы [ 2 ]

1 голос
/ 04 мая 2019

[...] макеты битовых полей определяются реализацией.

Некоторые аспекты определяются реализацией. Другие не определены, например, размер адресуемой единицы хранения, зарезервированной для битового поля.

Это практически проблема?

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

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

Я заметил SysV ABI для x86-64, например, определяет, как должны быть расположены битовые поля, поэтому я полагаю, использование битовых полей на этой платформе не должно быть проблематичным, даже если я смешать объектный код, сгенерированный разными компиляторами.

Использование битовых полей не создает проблемы совместимости при смешивании кода, на который можно полагаться при создании и использовании идентичных макетов битовых полей.

Использование битовых полей не создает проблемы переносимости 1030 * для кода, который избегает зависимости от деталей макета битового поля.

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

Битовые поля аналогичным образом стандартизированы и на других платформах? (Я в основном заинтересованы в Linux (SysV ABI), MacOs и CygWin.)

Вообще говоря, для размещенных реализаций (включая все ваши примеры) будет платформа ABI, определяющая макет битового поля, для взаимодействия программного обеспечения внутри платформы. ABI не имеет особого отношения к автономным реализациям, но многие, если не все, такие реализации указывают полную информацию о макетах битовых полей. Если вас беспокоит вопрос о том, можете ли вы связать код, использующий битовые поля, скомпилированный с различными реализациями C для одной и той же платформы, и получить правильно работающую программу, тогда ответ почти наверняка «да».

1 голос
/ 04 мая 2019

Как обычно в программировании, нет простого ответа. Это всегда зависит от многих обстоятельств.

IMO, ответ зависит от того, для чего вы планируете их использовать.

Если вы хотите иметь конкретные целые числа битового размера с предсказуемым поведением и читаемым кодом - да

struct 
{
    unsigned cnt: 3;
}three_bit_counter;

three_bit_counter.cnt++;

Если вы программируете ОК - Да

Если вы хотите использовать один и тот же код и «упаковать» данные в структуры битовых полей - нет.

Это только некоторые примеры. При кодировании полезно учитывать множество вариантов, а не высказывать мнения «гуру».

struct 
{
    unsigned cnt: 3;
    unsigned cnt1: 4;
}three_bit_counter;

unsigned cnt;


void inccnt(void)
{
    three_bit_counter.cnt++;

}
void inccnt1(void)
{
    three_bit_counter.cnt1++;

}

void inccntmask(void)
{
    unsigned tmp = cnt & 7;
    tmp++;
    tmp &= 7;

    cnt &= ~7;
    cnt |= tmp;

}

void inccnt1mask(void)
{
    unsigned tmp = cnt & (0b1111 << 3) >> 3;

    cnt &= ~(0b1111 << 3);
    tmp++;
    tmp &= 0b1111;
    cnt |= tmp << 3;

}
...