Почему битовые поля должны быть целочисленными?

В каждой книге, которую я искал, в каждом учебнике по Интернету и в каждом вопросе о SO говорится, что битовые поля должны быть целочисленного типа. Это почему?

4 ответа

Решение

Давайте зададим обратный вопрос:

  • Какие типы, кроме целочисленного типа, могут быть битовыми полями?

Давайте рассмотрим варианты:

  1. void: не значение - не сработает.
  2. Указатели: но указатели на машине имеют фиксированный размер; Вы не можете использовать 13 битов указателя и ожидать, что это будет что-то значить.
  3. Структуры, союзы: но тогда вы не имеете дело с простыми полями.
  4. Что оставляет float или же double, но это тщательно разработанные форматы, и вы не можете просто использовать 13 бит из double (или же float) и ожидать, что это будет что-то значить.

Итак, после того, как вы прошли через опции, у вас остались различные типы целых чисел: char, short, int, long, long long (в подписанной и неподписанной формах) и _Bool, Из этих опций стандарт указывает, что вы можете использовать _Bool, unsigned int, signed int и "простой" int:

ISO / IEC 9899: 2011 §6.7.2.1 Структура и спецификаторы типа объединения

Bit5 Битовое поле должно иметь тип, который является квалифицированной или неквалифицированной версией _Bool, signed int, unsigned intили некоторый другой тип, определенный реализацией. Это определяется реализацией, разрешены ли атомарные типы.

Поведение "равнины" int определяется реализацией: он может быть подписанным или неподписанным (примерно как "обычный") char может быть подписан или не подписан). Таким образом, комментарий от jxh является правильным; Я был небрежно цитировал слишком много типов (но я перефразировал вещи так, чтобы это не вводило в заблуждение).

Обратите внимание, что большая часть поведения битовых полей определяется реализацией; кроме обозначений, очень мало что указано в стандарте.

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

Почти любой другой тип данных подвергается некоторой интерпретации: числа с плавающей запятой состоят из двух частей: мантиссы и экспоненты; строки... ну, строки байтов (или значения Unicode). Структура или указатель на массив может представлять почти все.

Например, я могу легко хранить 32 бита в целых числах и извлекать их примерно так (псевдокод c-like):

int GetBit(int field, int position)
{
    return field & 1 << position;
}

Где возвращаемое значение 1 или 0, хранится в целом числе.

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

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

C.11 §6.7.2.1 ¶5:

Битовое поле должно иметь тип, который является квалифицированной или неквалифицированной версией _Bool, signed int, unsigned intили какой-либо другой тип, определенный реализацией. Это определяется реализацией, разрешены ли атомарные типы.

C.11 §6.7.2.1 ¶10:

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

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

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

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

Другие вопросы по тегам