Что такое бит-бит
Возможный дубликат:
Практическое использование битовых полей нулевой длины
Почему в некоторых структурах есть битовые поля с нулевой шириной и почему это необходимо?
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
Пожалуйста, объясните, почему эти значения являются отрицательными, и расположение памяти этих переменных внутри структуры?
Ответы
Ответ 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 для положительного). Что касается битовых полей нулевой длины, см. Здесь: Практическое использование битовых полей с нулевой длиной