Подтвердить что ты не робот

Что такое бит-бит

Возможный дубликат:
Практическое использование битовых полей нулевой длины

Почему в некоторых структурах есть битовые поля с нулевой шириной и почему это необходимо?

struct foo {
  int    a:3;
  int    b:2;
  int     :0; // Force alignment to next boundary.
  int    c:4;
  int    d:3;
};

int main()
{
        int i = 0xFFFF;
        struct foo *f = (struct foo *)&i;
        printf("a=%d\nb=%d\nc=%d\nd=%d\n", f->a, f->b, f->c, f->d);
        return 0;
}

Вывод программы выше

[email protected]:~/programs/test$ ./a.out
a=-1
b=-1
c=-8
d=0

Пожалуйста, объясните, почему эти значения являются отрицательными, и расположение памяти этих переменных внутри структуры?

4b9b3361

Ответ 1

От этот первый удар попал в поиск Google:

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

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

int main()
{
    struct foo f;
    memset(&f, 0xff, sizeof(f));
    printf("a=%d\nb=%d\nc=%d\nd=%d\n", f.a, f.b, f.c, f.d); // print fields as signed
    printf("a=%u\nb=%u\nc=%u\nd=%u\n", f.a, f.b, f.c, f.d); // print fields as unsigned
    return 0;
}

Ответ 2

Макет памяти "зависит", и вы не можете рассчитывать на какой-либо конкретный макет из какого-либо конкретного компилятора. Фактически, вы можете увидеть разный макет из любого данного компилятора, изменив его настройки. Не пытайтесь угадывать, интуитивно, или зависеть от макета.

Отрицательные - все ваши элементы int, которые подписаны, поэтому они являются отрицательными, так как вы инициализировали каждый бит до 1, поэтому у вас есть знаковые биты. Что касается d - бьет меня. Опечатка?

Ответ 3

Как указано здесь, битовые поля нулевой длины добавляют выравнивание между битовыми полями. Если у нас есть несколько битовых полей подряд, их макет компактен, но если мы хотим выровнять один из них с байтом/словом/словом dword, нам нужно поставить бит-бит нулевой длины между этим и предыдущим.

Пример из приведенной выше ссылки:

struct on_off {
                  unsigned light : 1;
                  unsigned toaster : 1;
                  int count;            /* 4 bytes */
                  unsigned ac : 4;     // this and
                  unsigned : 4;        // this and
                  unsigned clock : 1;  // this bitfields are next to each other
                  unsigned : 0;
                  unsigned flag : 1;   // this bitfield is at a 4 bytes boundary.
                 } kitchen ;

Ответ 4

Номера отрицательны, потому что битполы подписаны, т.е. если у вас есть переменная signed char, ее размер составляет 8 бит, который может содержать 256 различных значений. Половина значений положительна, остальные отрицательны и 0. Самый старший бит указывает знак (1 для отрицательного, 0 для положительного). Что касается битовых полей нулевой длины, см. Здесь: Практическое использование битовых полей с нулевой длиной