rozmiar struktury z polami bitowymi

0
struct 
{
      int TypTerenu:4;
      int Rzeka:1;
      int Forteca:1;
      int TypDrogi:2;
} pola;

Załóżmy ze mamy taki kod,no to zmienna pola zajmuje w pamieci rozmiar 4x int(4bajty) czyli 16 bajtow,zgadza sie? bo gdzies wyczytalem ze w tym przypadku zmienna pole jest przechowywana w komórce o rozmiarze typu int...

0

czemu,skoro rozmiar char to 1 bajt,a tu mamy jakby 4zmienne char?

0

Popatrzyłeś w ogóle na tamte linki? :|

dla klasy powiedzmy takiej:

struct
{
      char A:4;
      char B:1;
      char C:1;
      char D:2;
} pola;

mapa pamięci wygląda tak:

/              A              \ /  B  \ /  C  \ /      D      \
[bit 0] [bit 1] [bit 2] [bit 3] [bit 4] [bit 5] [bit 6] [bit 7]        = 8 bitów = char

Próba przypisania np. C = 2 skończy się w najlepszym razie błędem kompilacji, bo C zajmuje 1 bit czyli może przyjmować wartość 1 albo 0.

Jak to się dzieje w twoim przykładzie, gdzie z inta jest wykorzystane jakby 8 bitów a 24 zostają wolne nie jestem pewien, ale prawdopodobnie są nieużywane.

0

a czy zawsze pola bitowe są przechowywane w pamięci w jednostce o rozmiarze int?

0

Słyszałeś o czymś takim jak samodzielność?

Nie, są przechowywane w takiej ilości pamięci jaką zajmują (ale wyrównywane do bajtów) - patrz mój poprzedni post.

Aczkolwiek kompilatory zazwyczaj domyślnie pakują struktury do 4 bajtów, czyli rozmiaru int, więc jeśli tego nie wyłączysz manualnie to tak, zawsze zajmują rozmiar int.

0

a co nam daje że podajemy typ,char,int,unsigned int,skoro pola bitowe są przechowywane obok siebie i są wyrównywane do bajtów?

0

Odpowiednie ich traktowanie po wyciągnięciu z pamięci?

0

Tylko myli mnie takie coś co jest napisane w książce: oto fragmenty:

http://www13.speedyshare.com/files/23615684/download/Przechwytywanie.JPG

http://www11.speedyshare.com/files/23615686/download/Przechwytywanie2.JPG
Bo tam jest napisane cały czas o jednostce int,tak jakby to była główna jednostka dla pól danych

i tak przy okazji,dlaczego podana struktura:

struct szablon1
{
      int var1;
      char var2;
};

nie zajmuje 5 bajtow(1+4) tylko 8? czyżby było tak ze komputer dla każdej zmiennej przydziela tyle miejsce ile potrzebuje najwieksza ze zmiennych w danej strukturze?

co to by w takim razie była za oszczędność pamięci przy polach bitowych skoro komputer np w takim przypadku:

struct
{
      short var1:1;
      char var2:1;
}pola;

zajmują 2 bajty zamiast 2 bitów? Rozmiar sprawdzałem poprzez sizeof

0

nie zajmuje 5 bajtow(1+4) tylko 8?

Wspominałem wcześniej - kompilatory stosują pakowanie dla pól struktur - tak jakby zaokrąglają ich rozmiar w górę (to się jakoś nazywało po polsku ;) Matematycznie ang. 'ceil' albo po prostu sufit. ) do granicy słowa maszynowego - na 90% u ciebie 4 bajty.
Sprawia to że komputerowi (no ok, mikroprocesorowi) jest szybciej się do nich dostać, ale za to zajmują więcej pamięci. Do wyłączenie tego mechanizmu służy #pragma pack (w kompilatorach które to obsługują) np (przykład skopiowany skądś)

#pragma pack(push)       /* zapamiętaj bieżącą wartość wyrównania */
#pragma pack(1)          /* brak wyrównania */
struct {
	char a;          /* sizeof(a) = 1 */
	int  b;          /* sizeof(b) = 4 */
} S;                     /* sizeof(S) = 5 */
#pragma pack(pop)

zajmują 2 bajty zamiast 2 bitów?

Jesteś pewien że 2 bajty? Powinno raczej zajmować 4 (wyrównanie, patrz wyżej). Tak czy inaczej nie można "pomieszać" typu "short" z "char", więc zajmują zupełnie oddzielne bajty z którego w każdym używasz tylko jednego bitu.

 short    char   
??????b ???????b

gdzie ? to bit który nie jest używany, a b to bit którego używasz.

co to by w takim razie była za oszczędność pamięci przy polach bitowych

Pola bitowe nie służą do oszczędzania pamięci (w 99.9% przypadków nie, ja nie widziałem takiego zastosowania ale potrafię sobie wyobrazić).
Pola bitowe przydają się np. kiedy twoja aplikacja współpracuje z jakimś kapryśnym zewnętrznym urządzeniem które wymaga np. (dziwny przykład) podania na pierwszych 3 bitach dnia tygodnia, na kolejnych 2 - pory roku a na pozostałych, powiedzmy, koloru.
Bez pól bitowych zrobienie czegoś takiego byłoby męczarnią (przesunięcia bitowe, maski itd) a pola bitowe pozwalają z czymś takim w miarę bezboleśnie pracować.

0

Pola bitowe są używane w celu oszczędzania pamięci lub do operacji niskiego poziomu wymagających zmian pojedynczych bitów.

Zródło:wikipedia

tak tylko wyjaśniam skąd mam tą informacje;p

0

W takim razie może czas zacząć uczyć się z bardziej wiarygodnych źródeł? ;)

0

a czy mógłby mi ktoś wyjaśnić,dlaczego taka mała struktura zajmuje az 16 bajtow,i jak jest ona rozmieszczona w pamieci?

struct czcionka
{
       unsigned int typ : 8;
       unsigned int     : 0;
       unsigned int rozmiar : 7;
       unsigned int     : 0;
       unsigned int wyrownanie : 2;
       unsigned int wytluszczenie : 1;
       unsigned int kursywa : 1;
       unsigned int podkreslenie : 1;
};
0

Skoro używasz :0 to chyba wiesz co to znaczy - kompilator zostawia tam "puste miejsce" i następne pole zaczyna się od kolejnej jednostki pamięci (reszta wolnego miejsca w tej jednostce jak zwykle nieużywana).

Czyli (trzecia chyba w tym wątku) mapa pamięci:

/  sizeof(int)   \ /     sizeof(int) \  /       sizeof(int)            \
 8 bitów  (reszta)   7 bitów   (reszta)   2b.   1b.   1b.   1b.    (reszta)
[  typ  ] [  -  ]  [ rozmiar ] [   -  ]  [wyr.][wyt.][kur.][pod.] [  -  ]

Dokładnie 12 bajtów.

Nie wiem czemu u ciebie zajmuje 16 bajtów - u mnie zajmuje 13 bajtów, tak jak powinna. (Jakiego kompilatora używasz?)

0

uzywam Dev-C++, aha,ja myślałem że jak używam :0 to wyrównanie nie jest do słowa tylko do bajtu

0

a mam teraz jeszcze jedno pytanie,za zadanie miałem napisac program,który zarządza czcionką,i np przesyła dane do jakiegos urzadzenia(ale ja mialem tylko napisac program ktory przygotowuje pakiet danych oczywiscie)

I teraz tak:
pierwsze 8 bitów przechowuje info o rodzaju czcionki(od 0 do 255);
kolejne 7 bitów przechowuje info o rozmiarze(od 0 do 127);
potem kolejny bit zawiera info o wyrownaniu(0-lewe 1-prawe);
kolejny bit o wytluszczeniu(0-wyl 1-wl)
kolejny bit o kursywie
kolejny bit o podkresleniu

za zadanie miaeln nie uzywac struktur z polami lecz jednej zmiennej,oto program:

#include <stdio.h>




void menu(void);
void _typ(int*wsk);
void _rozmiar(int*wsk);
void _wyrownanie(int*wsk);
void _wytluszczenie(int*wsk);
void _kursywa(int*wsk);
void _podkreslenie(int*wsk);











int main(void)
{
    int dane=0;
    int koniec=0;
    int wybor;
    
    while (koniec!=1)
    {
          
    printf("\n\nLiczba dane to: %d",dane);
    menu();
    printf("Wybor opcji: ");
    scanf("%d",&wybor);
    
    switch (wybor)
    {
           case 1 : _typ(&dane);
                    break;
           case 2 : _rozmiar(&dane);
                    break;
           case 3 : _wyrownanie(&dane);
                    break;
           case 4 : _wytluszczenie(&dane);
                    break;
           case 5 : _kursywa(&dane);
                    break;
           case 6 : _podkreslenie(&dane);
                    break;
           case 7 : koniec=1;
                    break;
           default: printf("Blednie wybrana opcja\n\n");
                    koniec=0;
    }
    
    }
                   
    puts("\nKONIEC");
    
    getchar();
    getchar();
    return 0;
}













void menu(void)
{
     printf("\n1 Zmiana czcionki        2 Zmiana rozmiaru   3 Zmiana wyrownania");
     printf("\n4 Wyl\\Wl wytluszczenie  5 Wyl\\Wl kursywe   6 Wyl\\Wl podkreslenie");
     printf("\n7 Koniec");
     puts("");
}



void _typ(int*wsk)
{    
     int num;
     int maska=255;
     printf("Wybierz typ czcionki (0-255) : ");
     while (scanf("%d",&num)!=1 || num<0 || num>255)
     {
           puts("Blednie wprowadzona wartosc");
     }
     maska=(~maska);
     *wsk&=maska;
     *wsk|=num;
     
}
     
     
     
     
void _rozmiar(int*wsk)
{    
     int num;
     int maska=32512;
     maska=(~maska);
     printf("Wybierz rozmiar czcionki (0-127) : ");
     while (scanf("%d",&num)!=1 || num<0 || num>127)
     {
           puts("Blednie wprowadzona wartosc");
     }
     *wsk&=maska;
     num<<=8;
     *wsk|=num;
}





void _wyrownanie(int*wsk)
{    
     int num;
     int maska=32768;
     maska=(~maska);
     printf("Wybierz rodzaj wyrownania (0-lewo 1-prawo) : ");
     while (scanf("%d",&num)!=1 || num<0 || num>1)
     {
           puts("Blednie wprowadzona wartosc");
     }
     
     *wsk&=maska;
     num<<=15;
     *wsk|=num;
}






void _wytluszczenie(int*wsk)
{    
     int num;
     int maska=65536;
     maska=(~maska);
     printf("Wylacz\\Wlacz czcionki(0-wylaczone 1-wlaczone): ");
     while (scanf("%d",&num)!=1 || num<0 || num>1)
     {
           puts("Blednie wprowadzona wartosc");
     }
     *wsk&=maska;
     num<<=16;
     *wsk|=num;
     
}





void _kursywa(int*wsk)
{    
     int num;
     int maska=131072;
     maska=(~maska);
     printf("Wylacz\\Wlacz kursywe czcionki(0-wylaczone 1-wlaczone): ");
     while (scanf("%d",&num)!=1 || num<0 || num>1)
     {
           puts("Blednie wprowadzona wartosc");
     }
     
     *wsk&=maska;
     num<<=17;
     *wsk|=num;
}





void _podkreslenie(int*wsk)
{    
     int num;
     int maska=262144;
     maska=(~maska);
     printf("Wylacz\\Wlacz podkreslenie czcionki(0-wylaczone 1-wlaczone): ");
     while (scanf("%d",&num)!=1 || num<0 || num>1)
     {
           puts("Blednie wprowadzona wartosc");
     }
     
     *wsk&=maska;
     num<<=18;
     *wsk|=num;
}


Wydaje mi się iż działa on poprawnie,ale chciałbym się upewnić,bo zastanawia mnie fakt,gdy np urzadzenie jakies o rozmiarze pobiera informacje z bitów od 9 do 15 ,to czy ono jakby wycina ten kawalek i tworzy z tego liczby(np 127 przy wszystkich wlaczonych) i wtedy na podstawie tej liczby okresla rozmiar czy może np stosuje maske do wyzerowania wszystkich bitów poza z tym info i wtedy zamienia na liczbe,a to juz wtey bedzie calkiem inna liczba..

0

Sprawdziłem poprawność, wygląda na to że jest ok.

1: 123 = 1111011
2: 100 = 1100100
3: 1   = 1
4: 0   = 0
5: 1   = 1
6: 1   = 1

6E47B = 1 1 0 1 1100100 01111011

Odnośnie pytania - "normalne" urządzenie używa do tego najpierw maski bitowej a później przesunięcia bitowego np.

  10011010 
& 00111000
  00011000
  ---------
  00011000
>> 3
  00000011

I w ten sposób wydobywa dane.

0

ok,dzięki:) myśle że temat można zamknać bo zaczynam rozdział o preprocesorze i bibliotece C :) Dzięki panowie za pomoc:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1