Не понимаю описание битового поля из стандарта C - PullRequest
3 голосов
/ 22 июня 2010

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

Я не могу получить эти строки. Не могли бы вы объяснить?

Ответы [ 3 ]

6 голосов
/ 28 января 2011

"может ли поле перекрывать границы слов, определяется реализацией.

Рассмотрим два слова памяти, где размер слова, скажем, 32 бита:

[31] [30] [29] ... [2] [1] [0] | [31] [30] [29] ... [2] [1] [0]

Если бы у нас была структура:

struct X
{
    int a : 30;
    int b : 4;
};

Тогда компилятор мог бы поставить поле b таким образом, чтобы часть была в каждом слове, или он мог бы оставить пробел, чтобы все b попадали во второе слово.:

[31] [30] [29] ... [2] [1] [0] | [31] [30] [29] [28] ... [2] [1] [0]
a--------------------a b-----------------b
OR
a--------------------a    GAP    b-----------------b

Почему он может оставить GAP? Потому что тогда, когда он хочет читать или писать b, ему нужно работать только с одним словом в памяти - это обычно быстрее и проще, и требует меньше инструкций процессора.

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

Если бы мы изменили нашу более раннюю структуру, мы могли бы явно запроситьпробел:

struct X
{
    int a : 30;
    int   : 2;  // unnamed field
    int b : 4;
};

Это говорит "оставьте 2 бита между a и b - им не нужен идентификатор (имя), потому что я никогда не буду спрашивать, что в них, или нужно будет спрашивать их значениебыть изменен ". Но вы не должны делать это 2 просто так, чтобы30 + 2 == 32 (размер нашего слова) ... вы можете спросить, какие промежутки вам нравятся, где угодно.Это может быть полезно, если вы имеете дело со значениями с какого-либо аппаратного устройства, и вы знали, какие были некоторые биты, но не другие, или вам просто не нужно было использовать некоторые из них - вы можете просто оставить их без названия для документированияВаша незаинтересованность при сохранении компилятором пространства именованных битовых полей с необходимыми смещениями в слове, необходимом для соответствия использованию оборудования.

специальная ширина 0 может использоваться для принудительного выравнивания по следующему словуborder. "

Это просто означает, что компилятор может вычислить, сколько бит осталось в частично заполненном слове, и перейти к началу следующего слова. Так же, как мы убедились, что b начал в новомслово, добавив 2-битное поле выше (учитывая, что a было 30 бит, а размер слова 32), мы могли бы иметь ...

struct X
{
    int a : 30;
    int   : 0;  // unnamed field
    int b : 4;
};

... и компилятор сработаетДля нас 2. Таким образом, если мы изменим a на какой-то другой размер или закончим компиляцию для 64-битного размера слова, компилятор бесшумно адаптируется кПоведение без необходимости исправления безымянного поля.

1 голос
/ 22 июня 2010

Как правило, если адрес выровнен по словам, процессор может выполнять операции быстрее. Слово обычно составляет 32 бита или 4 байта.

Типичные процессоры выровнены по «слову», что означает, что они могут извлечь целое «слово» памяти за одну операцию. Когда значение совпадает с несколькими значениями, процессор должен выполнить несколько операций, чтобы получить одинаковые данные. Иногда это неизбежно, например, если вы используете «двойное слово», но если у вас есть одно слово, которое простирается через границу слова, ЦПУ придется выполнить 2 операции, чтобы извлечь одно слово данных.

Пример выровненного по слову значения: 0x10000004, 0x10000008. Поскольку слово имеет длину 4 байта, адрес должен делиться на 4. Значение, не выровненное по слову, равно 0x10000003.

Программисту все операции будут работать как положено, но под капотом ЦП должен выполнить 1 операцию памяти для чтения или записи в 0x10000004, тогда как он должен выполнить 2 операции памяти для чтения или записи в 0x10000003, поскольку он пересекает граница слова.

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

0 голосов
/ 22 июня 2010

Во-первых, это в основном связано с «aligment» памяти. Компиляторы часто выравнивают переменные или поля по границам слова, слово 32 бита на 32-битной платформе. Это означает, что два bool будут иметь первый байт в разных словах, а не два последовательных байта.

Битовые поля могут вызвать размещение в памяти: вы можете быть уверены, что конкретное поле использует только 3 бита, если его значения находятся в диапазоне 0-7.

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

Если вы используете :0, он автоматически выровняется по границе следующего слова.

Как правило, это поведение не требуется, если вы не настраиваете производительность каким-либо образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...