Что представляет собой поле бит нулевой ширины

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

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

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; } 

Вышеупомянутая программа

 manav@os-team:~/programs/test$ ./a.out a=-1 b=-1 c=-8 d=0 

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

    Из этого первого попадания в поиск Google :

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

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

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

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

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

    Как указано здесь , битовые поля нулевой длины добавляют выравнивание между битовыми полями. Если у нас есть несколько битовых полей подряд, их макет компактен, но если мы хотим выровнять один из них с байтом / словом / словом 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 ; 

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