2012-12-10 7 views
14

Powiel możliwe:
Practical Use of Zero-Length BitfieldsCo jest zero-width bitowe pole

Dlaczego niektóre konstrukcje mają zerową szerokość pola bitowe, i dlaczego jest to konieczne?

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

Wyjście powyższego programu jest

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

proszę wyjaśnić dlaczego te wartości są ujemne, a układ pamięci tych zmiennych wewnątrz struktury?

+1

Jest to odpowiedź firmy Microsoft, proponuję spojrzeć: http://msdn.microsoft.com/en-us/library/ewwyfdbe(v=vs. 71) .aspx, mimo to wyrównanie jest zawsze zależne od kompilatora. –

+0

struct { int a: 3; int b: 2; int: 0; int c: 4; int d: 3; }; , która daje układ 000aaabb 0ccccddd zamiast bez: 0; 0000aaa bccccddd Pole szerokości 0 mówi, że następujące pola bitowe powinny zostać ustawione na następnym obiekcie atomowym (znak). Kolejność danych zadeklarowanych jako pola bitowe jest od małego do wysokiego bitowego lub w inny sposób w zależności od architektury. –

Odpowiedz

8

Od this first hit on a Google search:

pól bitowych o długości od 0 musi być bezimienny. Nienazwanych pól bitów nie można odwoływać się ani inicjować. Pole bitowe o zerowej szerokości może spowodować wyrównanie następnego pola na następnej granicy pojemnika, w której kontener ma taki sam rozmiar, jak bazowy typ pola bitowego.

Co do drugiej części pytania, ustawić niektóre z bitfields w swojej struktury do wszystkich 1s, a ponieważ są te pola podpisał wówczas prowadzi to do ujemnej wartości dla tych pól. Możesz to zobaczyć bardziej efektywnie, jeśli ustawisz całą strukturę na 1s i spojrzysz na wartości zarówno w podpisanych, jak i niepodpisanych reprezentacjach, np.

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

Układ pamięci „to zależy” i nie można liczyć na konkretnym układzie od konkretnego kompilatora. W rzeczywistości możesz zobaczyć inny układ z dowolnego kompilatora, zmieniając jego ustawienia. Nie próbuj zgadywać, intuicyjnie lub polegać na układzie.

Negatywy - wszystkie twoje elementy to int s, które są podpisane, więc są ujemne, ponieważ zainicjalizowałeś każdy bit na 1, więc masz ustawione bity znaków. Jeśli chodzi o d - bije mnie. Typo?

+0

Nie odpowiedziałeś na główną część pytania - jaki jest cel bitfieldu o zerowej szerokości? –

1

Liczby są ujemne, ponieważ pola bitowe są podpisane, tj. Jeśli masz zmienną signed char, jej rozmiar to 8 bitów, które mogą zawierać 256 różnych wartości. Połowa wartości jest dodatnia, reszta jest ujemna i 0. Najbardziej znaczący bit oznacza znak (1 dla ujemnego, 0 dla pozytywnego). Odnośnie bitfieldów o zerowej długości, zobacz tutaj: Practical Use of Zero-Length Bitfields

2

Jak podano here, bitfieldy o zerowej długości dodają wyrównanie między bitfieldami. Jeśli mamy kilka pól bitowych z rzędu, ich układ jest zwarty, ale jeśli chcemy wyrównać jeden z nich do granicy bajt/słowo/dword, musimy umieścić pole bitowe o zerowej długości pomiędzy tym i poprzednim.

Przykład z linku powyżej:

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 ;