PasjaGSM.pl
  Jesteś w: Forum > Najlepszy sposób na zmienianie ustawień w aplikacjach


Najlepszy sposób na zmienianie ustawień w aplikacjach

Forum.PasjaGSM.pl » ...:Sprzęt:... » Nokia » DCT-3 » [DCT3] Modyfikacje HW i SW » NokiX » Programowanie » Najlepszy sposób na zmienianie ustawień w aplikacjach
Poprzedni temat «» Następny temat
Autor Wiadomość
 
druidbartek 
Expert



Telefon: DCT-3
Operator: Era
Pomógł: 39 razy
Wiek: 31
Dołączył: 13 Wrz 2005
Posty: 1006
Skąd: Wrocław
Wysłany: 2006-01-02, 18:00   Najlepszy sposób na zmienianie ustawień w aplikacjach

chodzi mi o to że np w periodic table było konieczna jakaś zmienna czy coś za pomocą której zmieniał sie pierwiastek itd
w sumie użyłem (aż) tylu zmiennych

int i=0; // od 0 do 117 to jest właśnie numer pierwiastka
int p=1; // od 1 do 7 było potrzebne w menu - to były kolejne pozycje
int w=0; // 0 - map, 1 - base - stan aplikacji - czy jest wyświetlany układ czy menu
int k=1; // help 1 - lewo, 2-prawo - to jest czy wyświetlany jest opis z prawej czy lewej strony

chodzi mi o to w jaki sposób zrobić to bardziej "profesjonalnie" żeby nie zżerało tyle RAMu, Yak stosował jakieś struktury czy coś ale nie bardzo to łapie. Bo w niektórych przypadkach wystarczyłoby użycie pojedynczych bitów jeśli zwracane są tylko 2 wartości itd

zrozumiał ktoś o co mi chodzi bo trochę to pokręciłem...
^
 
     
AdSense


riger 
Expert
Elektronik...



Telefon: 5200
Operator: Orange
Pomógł: 25 razy
Wiek: 27
Dołączył: 26 Lut 2005
Posty: 1483
Skąd: 50km do Gdanska
Wysłany: 2006-01-02, 18:08   

istnieje cos takiego jak tablice statystyczne przez co nie musisz wprowadzac kazdej zmiennej z osobna wiec zapraszam do lektury. >>tutaj<<
^
 
 
     
druidbartek 
Expert



Telefon: DCT-3
Operator: Era
Pomógł: 39 razy
Wiek: 31
Dołączył: 13 Wrz 2005
Posty: 1006
Skąd: Wrocław
Wysłany: 2006-01-02, 18:12   

no ale mi po trochu chodzi żeby tam zamiast całymi liczbami to pojedyncze bity zmieniać np że 01010000 by oznaczało że opcja 2 i 4 są włączone a pozostałe nie czy coś takiego : /
^
 
     
grzesiek1711 
Starszyzna
heh 3x P????Team :P



Telefon: 3310+6600
Operator: Plus
Pomógł: 14 razy
Wiek: 30
Dołączył: 29 Sie 2004
Posty: 632
Skąd: prawie Koszalin
Wysłany: 2006-01-03, 15:22   

druidbartek, tutaj masz zmienne int (one zajmują po 4bajty każda!!) co daje w sumie 16 bajtów pamięci a potrzebujesz:

dla i od 0 do 117 - mieści się w 128 czyli 7 bitów
dla p od 1 do 7 - mieści się w 8 czyli 3 bity
w 0 lub 1 czyli jeden bit
k 1 lub 2 czyli jeden bit

daje to w sumie 7+3+1+1=12bitów czyli niecałe 2 bajt, w porównaniu do 16 to jest osiem razy mniej...<wow>

po pierwsze nie używaj int tylko ubyte (popatrz na Yak'a) to zaoszczędzi Ci miejsca (1 bajt zamiast 4).

co do zapisywania pojedynczych bitów w zmiennej mozna to zrobić z przesuwaniem w lewo, w prawo czy też napisać procedurki konerwtujące liczbę na stringa w postaci "00101010", i odczytywać konkretny znak tej zmiennej, ale to kolejna jest jednak zmienna. nie wiem jak Yak to robi..
^
 
 
     
sander18 
Starszyzna
Nie Wie Co Pisze ;)



Telefon: nokie
Operator: Orange
Pomógł: 29 razy
Wiek: 34
Dołączył: 02 Mar 2005
Posty: 511
Skąd: z kątowni ;)
Wysłany: 2006-01-03, 17:20   

sprobuj za pomoca flag, tak jak jest w breakerze.
Kod:
struct game
{
 ....
 UBYTE flags;           // game flags (see below; GF_...)
 ...
};

// game flags
#define GF_CHOOSE_BOARD      (0x01)
#define GF_PAUSE             (0x02)
#define GF_BALL_GLUED        (0x04)
#define GF_TITLE_DRAWN       (0x08)
#define GF_GAME_OVER         (0x80)

i pozniej uzywanie flag jest np:
Kod:
if(game->flags&GF_BALL_GLUED) move_ball(game->ball_x+game->paddle_x-oldx,44);

a zeby ustawiac flagi robisz cos np takiego:
Kod:
 game->flags|=GF_BALL_GLUED;
 game->flags&=~GF_TITLE_DRAWN;
_________________
W dżungli amazońskiej odkryto nowy gatunek kameleona. Ma 65 tys. kolorów i polifoniczne dzwonki :D
^
 
 
     
druidbartek 
Expert



Telefon: DCT-3
Operator: Era
Pomógł: 39 razy
Wiek: 31
Dołączył: 13 Wrz 2005
Posty: 1006
Skąd: Wrocław
Wysłany: 2006-01-03, 19:43   

grzesiek1711, sander18, wielkie dzięki. właśnie o to mi chodziło. te inty to stąd że właśnie nie wiedziałem co ile zżera teraz już wiem. po części stąd sie to wzieło że Yak napisał że rezygnuje z własnych typów tych UBYTE itd na rzecz właśnie standardowych czyli int, char itp. więc kolejna wersja periodic będzie zżerała dużo mniej pamięci : ]

sander18, planujesz przepisać swojego ponga na VHAMa? ja mam o tyle problem z moją grą że np periodic pisałem od początku do końca a teraz jak utworzyłem gotowy projekt gry to dużo kodu jest dodane i jeszcze tego nie łapie ale czas (którego ciągle mało) pokaże...
^
 
     
sander18 
Starszyzna
Nie Wie Co Pisze ;)



Telefon: nokie
Operator: Orange
Pomógł: 29 razy
Wiek: 34
Dołączył: 02 Mar 2005
Posty: 511
Skąd: z kątowni ;)
Wysłany: 2006-01-03, 19:53   

druidbartek, no planuje go przepisac. zwlaszcza, ze pisalem go tak haotycznie, ze z pewnoscia jest tam sporo niedociagniec i rzeczy niepotrzebnych... no i mialem jeszcze dodac mozliwosc gry na dwoch graczy i zmienic algorytm "myslenia" komorki i jeszcze cos tam... ale od swiat nawet nie tknalem nokixa nie mowiac juz o sdk, bo po prostu czasu troche brak :/
_________________
W dżungli amazońskiej odkryto nowy gatunek kameleona. Ma 65 tys. kolorów i polifoniczne dzwonki :D
^
 
 
     
jaras 
Nowicjusz



Telefon: Nokia 5110
Operator: Plus
Pomógł: 2 razy
Wiek: 44
Dołączył: 09 Kwi 2005
Posty: 62
Skąd: "LAC: 41008" ;-)
Wysłany: 2006-01-04, 13:25   

Witam.

A Wy, Panowie, zapomnieliście już o innych typach w C? Jeśli czytacie "Kurs C++", to w Lekcji 3 macie opisane typy danych. Przepraszam, że Was tak pouczam, ale rzeczywiście, szkoda miejsca w pamięci na liczby z zakresu 0..117 zapisywane na 4 bajtach. :-/

Może przypomnę (dotyczy kompilatorów 32-bitowych, gcc w NokiX'ie - też):
  • intsignedsigned int - liczba całkowita 32-bitowa ze znakiem (-2147483648..2147483647).

  • unsigned intunsigned - liczba całkowita 32-bitowa bez znaku (0..4294967295).

  • short intshortsigned shortsigned short int - liczba całkowita 16-bitowa ze znakiem (-32768..32767).

  • unsigned short intunsigned short - liczba całkowita 16-bitowa bez znaku (0..65535).

  • char - liczba całkowita 8-bitowa (nie jest domyślnie określone czy ze znakiem, czy bez, dlatego lepiej do liczb używać jak niżej).

  • signed char - liczba całkowita 8-bitowa ze znakiem (-128..127).

  • unsigned char - liczba całkowita 8-bitowa bez znaku (0..255).
Znaczek "≡" powyżej oznacza, że zapisy są sobie całkowicie równoważne, a więc można zapisać w jeden sposób lub w inny bez zmiany działania programu i typu deklarowanej danej (po prostu jedne nazwy są krótsze, a drugie - czytelniejsze ;-).

Nie używajcie żadnych "ustrojstw" w stylu ubyte, gdyż nie są one standardowymi typami. Przecież możecie sobie na początku programu, dla krótszego zapisu, zrobić definicję:
Kod:
#define bajt unsigned char
lub nawet lepiej:
Kod:
typedef unsigned char bajt;
a potem tylko deklarować zmienne:
Kod:
    bajt mojazmienna;
    bajt mojatablica[10];
    bajt *wsknabajt;

To, jeśli chodzi o dane mieszczące się na jednym bajcie.

A co z danymi zawartymi na pojedynczych bitach?

Prawdę mówiąc, "Kurs C++" na ten temat zupełnie "milczy jak głaz" ;-). Chodzi mi o tzw. pola bitowe. Nie mam pojęcia tylko, czy @ yak w przerobionym do NokiX'a kompilatorze gcc je zaimplementował.

Jak się tego używa?

Definiuje się strukturę z polami bitowymi:
Kod:
struct strbit
{
    unsigned dana1 : 2;
    unsigned dana2 : 1;
    signed dana3 : 3;
} mojebity;

Tutaj:
  • struct strbit - deklaruje nazwę typu dla struktury z polami bitowymi, typu tego będzie można uzywać np. przy przekazywaniu parametrów do funkcji.

  • dana1 - jest polem o wielkości 2-bitowej, służącym do przechowania liczby całkowitej bez znaku, a więc w zakresie 0..3.

  • dana2 - jest polem o wielkości 1-bitowej, służącym do przechowania liczby całkowitej (dla jednego bitu nie ma znaczenia znak liczby :-), a więc: 0 i 1.

  • dana3 - jest polem o wielkości 3-bitowej, służącym do przechowania liczby całkowitej ze znakiem (ujemnej lub dodatniej), a zatem w zakresie -4..3.

  • mojebity - definiuje zmienną strukturalną (czyli składającą się z tych pól), której będzie można uzywać w programie.
Aby uzyskiwać dostęp do pól bitowych, posługujemy się zwykłą konstrukcją dostępu do pól struktury, np.:
Kod:
    mojebity.dana1=1;
    mojebity.dana2=0;
    mojebity.dana3=-2;

Od razu tylko jednak muszę napisać...

Nie wiem, w jaki sposób są zapamiętywane bity w polach bitowych. Nie pisałem jeszcze programów w NokiX'owym gcc (ani w zwykłym gcc), a swą wiedzę opieram tylko na standardzie ANSI (który czyni zalecenia dla projektantów kompilatorów), dlatego nie wiem, w jakiej kolejności w kolejnych bajtach zapisywane są kolejne pola bitowe. Najprawdopodobniej jest tak, że, dla powyższego przykładu, dana1 będzie zajmować bity najmniej znaczące: bity 0 i 1, dana2 - bit 2, dana3 - bity od 3 do 5. Jednak w tej sprawie musiałby się wypowiedzieć @ yak - wtedy sprawa stałaby się jasna.

Tymczasem, do tego czasu można używać stałych i operatorów bitowych, jak słusznie ktoś powyżej napisał.

Przesyłam serdeczne pozdrowienia.
_________________
Jarosław Krasuski (jaras)
^
 
 
     
yak 
Starszyzna



Telefon: Kilka DCT3
Operator: Vodafone
Pomógł: 20 razy
Wiek: 37
Dołączył: 21 Gru 2004
Posty: 774
Skąd: Bochum / Niemcy
Wysłany: 2006-01-05, 02:57   

po pierwsze cieszy mnie duze zainteresowanie. jaras'owi dziekuje tez za lekcje standardow - na pewno wszystkim sie przyda.

teraz konkrety. procesory ARM nokii sa 32-bitowe wiec int u nas ma 32 bity czyli 4 bajty. w razie mozliwosci prosze uzywac typow short oraz byte (oraz ich odpowiednikow unsigned).

jesli chodzi o przechowywanie flag to ja to robie tak jak pokazal sander18.

gcc w SDK to normalne gcc w najnowszej wersji 4.0.2 zmodyfikowane tylko w jednej kwestii. chodzi o interoperatywnosc trybow ARM i THUMB. poniewaz my uzywamy tylko THUMB i wstawiamy kod Rexx'em musialem troche zmienic sposob wywolywania funkcji poprzez ich wskazniki (a konkretnie wrocilem do rozwiazania stosowanego w starszych wersjach gcc). to wszystko, inne elementy kompilatora sa takie same wiec nie ma np. zadnych roznic w skladni.

tak wiec pola bitowe pokazane przez jaras'a powinny dzialac. sam nigdy ich jednak nie uzywalem i nie wiem jak gcc je przechowuje. istnieje "niebezpieczenstwo", ze po prostu przydziela tyle bajtow na kazde pole, aby sie ono tam zmiescilo. w powyzszym przypadku bylyby to 3 bajty co nie jest maksymalnie efektywne. byc moze zalezy to od optymalizacji ktora w moim sdk ustawiona jest na rozmiar kodu (parametr -Os do gcc). kod operujacy na calych bajtach bedzie bowiem krotszy. ale to sa tylko moje przypuszczenia ktorych nie moge niestety sprawdzic bo jestem jeszcze na wakacjach.

tak wiec nalezy sprawdzic czy kompilator pakuje pola bitowe i jesli tak to uzywac ich a jesli nie to metody, ktorej ja uzywam.

jest jeszcze inna rzecz. w nokixie istnieje cos takiego jak global_buffer. jest to 40 bajtow RAM'u uzywane przez rozne aplikacji nokii jako takie tymczasowe bufory globalne. np. kalkulator trzyma tam wpisywane liczby, wiele innych uzywa tego jako bufora do wpisywania tekstu w dialogach.

generalnie te 40 bajtow mozna wykorzystac jak sie chce pamietajac jednak, ze po wyjsciu z gry/aplikacji dane te zostana usuniete. nie przeszkadza to jednak przechowywac tam jakichs chwilowych stanow, ktore przy kazdym wejsciu do aplikacji sa resetowane. w wielu przypadkach mozna to zastosowac zamiast zmiennych globalnych.

domysle inkludy definuja objekt global_buffer jako tablice 40 bajtow:
extern unsigned char global_buffer[40];

jesli chcemy tego uzyc wlasnie w takiej formie to nic wiecej nie trzeba robic, po prostu odwolujemy sie do tej tablicy.

czesto jednak chcemy przechowac tam kilka roznych zmiennych. wtedy najlepiej zdefiniowac sobie strukture:

Kod:
struct global_data
{
 int x,y;
 float angle;
};


aby teraz odwolac sie do global_buffer jako do tej struktury musimy zastosowac rzutowanie, np.:

Kod:
((struct global_data)global_buffer).x = 5;


aby za kazdym razem tego nie pisac mozna stworzyc sobie makro:

Kod:
#define gdata ((struct global_data)global_buffer)


i potem uzywamy tego tak:

Kod:
gdata.x = 5;


oczywiscie nazwa gdata jest dowolna musimy jednak pamietac aby byla unikatowa i nie nazywac tak samo zadnej funkcji/zmiennej w programie (nawet lokalnej). jest to jednak trik dla wtajemniczonych i zalecam na poczatku stosowanie zmiennych globalnych - zawsze jak sie ktos wyrobi moze swoje dzielo pozniej zoptymalizowac.

Pozdrawiam
[Yak]
_________________
NokiX Ci się podoba? Kliknij i wyraź to!
^
 
 
 
     
jaras 
Nowicjusz



Telefon: Nokia 5110
Operator: Plus
Pomógł: 2 razy
Wiek: 44
Dołączył: 09 Kwi 2005
Posty: 62
Skąd: "LAC: 41008" ;-)
Wysłany: 2006-01-05, 03:36   

Witam.

To ja mam w takim razie pytania, jak najbardziej dotyczące tematu tego wątku. :-)

Na jakiej zasadzie działają zmienne globalne we własnych programach?

To znaczy, nie chodzi mi o wytłumaczenie, co to są zmienne globalne (ja sam mógłbym to komuś wytłumaczyć, jeśli ktoś tego nie wie ;-P), lecz o to gdzie są one przechowywane i jaki jest "czas życia" tych zmiennych.

Może rozwinę nieco to ostatnie zdanie...

Wyobraźmy sobie, że napisaliśmy kilka aplikacji (gry, jakieś narzędzia itp.) i one sobie działają w pamięci. Powiedzmy, że uruchomiliśmy grę i wyszliśmy z niej (ale chcemy ją potem kontynuować). Do tego, na przykład, uruchomiliśmy jeszcze jakąś inną aplikację, która coś tam sobie liczy w tle (za pomocą timer'ów) i też wychodzimy z niej. I tak dalej.

Przypominają mi się czasy komputerów Commodore czy Atari, kiedy robiło się muzyczkę grającą na przerwaniach IRQ, a do tego stacja dysków odczytywała jakieś dane z dyskietki, a w tym samym czasie działała jeszcze jakaś aplikacja, która coś tam rysowała na ekranie. Nie muszę chyba już pisać, że w tym samym czasie system wykonywał swoje normalne działania: odczyt klawiatury, odświeżanie liczników systemowych i tzw. "rejestrów cieni" itp. :-)

Oczywiście w programach można użyć zmiennych globalnych, np.:
Kod:
int zmienna1;
int zmienna2;
// itd.
albo też lokalnych statycznych (których "czas życia" normalnie jest równy zmiennym globalnym), np.:
Kod:
int funkcja(int parametr)
{
    static int zmienna1;
    static int zmienna2;

    // ...
}

Właściwie to i powinienem spytać właśnie też o to, CZY w ogóle można w programach używać zmiennych lokalnych statycznych, ale mam nadzieję, że tak. :-)

Ale, aby nie za bardzo skomplikować tego problemu, zilustruję to przykładem:
Kod:
// mój program

int moj_global;
Chciałbym, aby wartość powyższej zmiennej moj_global była dostępna dla aplikacji zawsze, gdy jest włączony telefon.

OK, domyślam się, że takie zmienne globalne i statyczne przechowywane są w pamięci RAM. Ale nie na stosie (bo tam są przechowywane tylko zmienne lokalne niestatyczne), tylko w pamięci, że tak powiem, "ogólnej". Jednak wiadomo, że tej pamięci nie mamy w ilości nieograniczonej. Mało tego, system też przecież używa RAM'u. Zatem musi być miejsce na zmienne globalne dla tej uruchomionej gry, tak samo dla tej uruchomionej aplikacji itp.

Dochodzę teraz do sedna swego pytania...

Ile tego miejsca jest? I jak to jest zrobione, że np. system nie zamaże obszaru RAM przeznaczonego na te zmienne dla swoich potrzeb? Czy w ogóle można zrobić takie zmienne, które będą istnieć przez cały czas, gdy telefon jest włączony? A jeśli nie można tego zrobić przez użycie zmiennych globalnych lub statycznych - to jak? Jeszcze inaczej zadam pytanie: czy zmienne globalne programu istnieją tylko w czasie, gdy aplikacja działa, a po jej opuszczeniu są usuwane, czy też może istnieją przez cały czas działania telefonu?

Oczywiście pytania odnoszą się do programów pisanych z użyciem SDK.

A może mi się wszystko pokiełbasiło, a pytania są zupełnie bez sensu? ;-)
Przypuszczam, że muszę zmienić sposób myślenia z "pecetowego" na "komórkowy". ;-D

Przesyłam serdeczne pozdrowienia.

PS. Sorry, @ yak, że Cię pouczam, ale zakradł się tu chyba mały błąd ;-):
yak napisał/a:
w razie mozliwosci prosze uzywac typow short oraz byte (oraz ich odpowiednikow unsigned).
Nie byte, tylko char. :-)
Ale może w gcc jest też typ byte - w takim razie przepraszam.
_________________
Jarosław Krasuski (jaras)
Ostatnio zmieniony przez jaras 2006-01-05, 04:21, w całości zmieniany 2 razy  
^
 
 
 
druidbartek 
Expert



Telefon: DCT-3
Operator: Era
Pomógł: 39 razy
Wiek: 31
Dołączył: 13 Wrz 2005
Posty: 1006
Skąd: Wrocław
Wysłany: 2006-01-05, 04:18   

yak napisał/a:

aby teraz odwolac sie do global_buffer jako do tej struktury musimy zastosowac rzutowanie, np.:

Kod:
((struct global_data)global_buffer).x = 5;


aby za kazdym razem tego nie pisac mozna stworzyc sobie makro:

Kod:
#define gdata ((struct global_data)global_buffer)



nie jestem pewien ale tam miało być chyba
Kod:
(*(struct global_data*)global_buffer).x = 5;

i
Kod:
(*(struct global_data*)global_buffer).x = 5;


jeśli sie mylę to poprawcie. btw udało mi się dzięki tym wszystkim informacją przenieść periodic na nowy SDK : ]

wielkie dzieki dla wszystkich

[ Dodano: 05-01-2006, 04:32 ]
no zastosowałem ten global_buffer i... jestem bardziej niż zadowolony. teraz aplikacja zżera połowe mniej ramu i te tymczasowe zmienne są kasowane. jeszcze drobne poprawki i wrzucam nową wersję : )
^
 
     
jaras 
Nowicjusz



Telefon: Nokia 5110
Operator: Plus
Pomógł: 2 razy
Wiek: 44
Dołączył: 09 Kwi 2005
Posty: 62
Skąd: "LAC: 41008" ;-)
Wysłany: 2006-01-05, 04:48   

druidbartek napisał/a:
nie jestem pewien ale tam miało być chyba
Kod:
(*(struct global_data*)global_buffer).x = 5;

i
Kod:
(*(struct global_data*)global_buffer).x = 5;


jeśli sie mylę to poprawcie.
Masz zupełną rację. :-)

Zapis global_buffer jest de facto wskaźnikiem, tak jak zmienna typu unsigned char *, a zatem trzeba by zrobić następująco:
Kod:
// żeby nie trzeba było pisać wciąż unsigned char, robimy typ 'bajt'

typedef unsigned char bajt;

// deklarujemy sobie wskaźnik na strukturę jako typ danych do rzutowania

typedef struct
{
    bajt x;            // jakaś jedna zmienna
    bajt y;            // jakaś druga zmienna
} *mojeglobaleptr; // nazwa od "moje globale pointer" ;-)

// robimy makro dla krótszego zapisu

#define mojeglobale ((mojeglobaleptr)global_buffer)

// używamy swoich zmiennych

int funkcja(bajt parametr)
{
    // ...
    mojeglobale->x=5;
    mojeglobale->y=3;
    // ...
}

Zauważ, że:
Kod:
(*wskaźnik_na_strukturę).pole
to jest to samo co:
Kod:
wskaźnik_na_strukturę->pole

Powiedzmy, że @ yak jest przemęczony ;-). Przecież nawet takiemu mistrzowi jak on może zdarzyć się pomyłka. ;-)

Pozdrawiam Cię.
_________________
Jarosław Krasuski (jaras)
^
 
 
 
druidbartek 
Expert



Telefon: DCT-3
Operator: Era
Pomógł: 39 razy
Wiek: 31
Dołączył: 13 Wrz 2005
Posty: 1006
Skąd: Wrocław
Wysłany: 2006-01-05, 06:44   

nie wiem czy o to chodziło z tym pakowaniem pól bitowych ale zrobiłem test i jeśli w sumie w strukturze było do 32 bity łącznie to był rezerwowane właśnie 4 bajty czyli np

Kod:
struct strbit
{
   unsigned dana1 : 2;
   unsigned dana2 : 4;
   unsigned dana3 : 5;
   unsigned dana4 : 7;
   unsigned dana5 : 7;
} mojebity;


pożarło 4 bajty czyli jest dobrze bo nie przydziela do każdego pola odowiedniej liczby bajtów tylko łącznie :]
^
 
     
jaras 
Nowicjusz



Telefon: Nokia 5110
Operator: Plus
Pomógł: 2 razy
Wiek: 44
Dołączył: 09 Kwi 2005
Posty: 62
Skąd: "LAC: 41008" ;-)
Wysłany: 2006-01-05, 09:19   

Pakowanie bitów w słowie - bo tak trzeba "fachowo" nazwać działanie kompilatora przy obsłudze pól bitowych - oznacza, że kolejne bity pól bitowyh struktury pakowane są po kolei w kolejnych bitach komórek pamięci, które ta struktura zajmuje. Trochę to może brzmi jak "masło maślane", ale zaraz wszystko wytłumaczę.

Z doświadczenia, które wykonałeś wynikałoby, że struktura struct strbit zajmuje najmniejszą niepodzielną jednostkę danych, jaką w kompilatorze 32-bitowym jest słowo (czyli właśnie 32 bity). Przypomnijmy tą definicję:
Kod:
struct strbit
{
    unsigned dana1 : 2;
    unsigned dana2 : 4;
    unsigned dana3 : 5;
    unsigned dana4 : 7;
    unsigned dana5 : 7;
} mojebity;

W zmiennej mojebity zatem najprawdopodobniej jest taki układ pól bitowych:
  • dana1 zajmuje bity od 0 do 2;
  • dana2 zajmuje bity od 3 do 6;
  • dana3 zajmuje bity od 7 do 11;
  • dana4 zajmuje bity od 12 do 18;
  • dana5 zajmuje bity od 19 do 25;
  • pozostałe bity, czyli od 26 do 31 pozostają niewykorzystane.
Gdyby zaś nie było pakowania bitów, kolejne pola bitowe zajmowałyby albo kolejne bajty, albo może nawet kolejne słowa 32-bitowe (!) pozostawiając mnóstwo niewykorzystanej przestrzeni.

Mam nadzieję, że wiesz o istnieniu jeszcze jednego operatora, jakim jest sizeof(nazwa_typu), zwracającego w wyniku ilość bajtów, jakie trzeba przeznaczyć na przechowanie danej o podanym typie nazwa_typu.

Jeśli chcesz zaś przekonać się czy rzeczywiście podany przeze mnie układ bitów w strukturze z polami bitowymi zajmuje bity o takich numerach, jak podałem powyżej, zrób inne doświadczenie:
Kod:
void test(void)
{
    // skrót dla typu "bajtowego"

    typedef unsigned char bajt;

    // deklaracja typu dla naszej struktury z polami bitowymi

    typedef struct
    {
        unsigned dana1 : 2;
        unsigned dana2 : 4;
        unsigned dana3 : 5;
        unsigned dana4 : 7;
        unsigned dana5 : 7;
    } typbit;

    // definicja tej struktury

    typbit mojebity;

    // definicja wskaźnika na zwykłe bajty

    bajt *mojebajty;

    // definicja tablicy liczb dla pól bitowych składających się z samych jedynek

    bajt bitypocz[] = {3, 15, 31, 127, 127};

    // inne pomocnicze pierdoły

    bajt i, j;

    // no to jedziemy z koksem ;-)

    mojebajty=(bajt *)&mojebity; //bajtowy wskaźnik ustawiamy na naszą strukturę
    for (i=0; i<sizeof(bitypocz); i++) // dla kolejnych pól bitowych...
    {
        for (j=0; j<sizeof(typbit); j++)
            mojebajty[j]=0; // zerujemy wszystkie bajty naszej struktury
        // w zależności od numeru pola ustawiamy odpowiednie pole na same jedynki
        switch (i)
        {
        case 0:
            mojebity.dana1=bitypocz[i];
            break;
        case 1:
            mojebity.dana2=bitypocz[i];
            break;
        case 2:
            mojebity.dana3=bitypocz[i];
            break;
        case 3:
            mojebity.dana4=bitypocz[i];
            break;
        case 4:
            mojebity.dana5=bitypocz[i];
            break;
        }
        // wyświetlamy kolejne bajty w postaci szesnastkowej
        printf("Dla mojebity.dana%d=%03d :", i+1, bitypocz[i]);
        for (j=0; j<sizeof(typbit); j++)
            printf(" %02X", mojebajty[j]);
        printf("\n");
    }
}

Jak to jeść? ;-)

Podczep tą funkcję do aplikacji dla telefonu, tak, żeby została tylko raz wykonana. Wśród różnych narzędzi NokiX'a zauważyłem programik o nazwie NokiXstdout.exe. Pozwoli on nam skorzystać z funkcji printf(), której użyłem w powyższym kodzie. That's all - wykonaj tą aplikację (wywołaj funkcję) i skopiuj sobie gdzieś wyniki jej działania z okna tego programiku.

Jak działa ta funkcja?
  • Na początku, po definicji naszej struktury z polami bitowymi mojebity, definiujemy również wskaźnik mojebajty na najzwyklejsze na świecie bajty.

  • Temu wskaźnikowi przypisujemy adres naszej struktury mojebity.

  • Teraz w pętli sterowanej przez zmienną i mamy numery kolejnych pól struktury mojebity.

  • Najpierw zerujemy wszystkie bajty (pętla j) zajmowane przez naszą strukturę (ile jest tych bajtów? ooo, właśnie tyle: sizeof(typbit) :-).

  • Potem do jednego z pól wpisujemy same jedynki (tablica bitypocz[] zawiera takie liczby, że składają się one z samych jedynek - tylu ile trzeba, aby zapełnić całe pole bitowe).

  • No, to teraz pozostało już tylko wyświetlić to co mamy w kolejnych bajtach (druga pętla j) zajmowanych przez naszą strukturę. Najlepiej będzie wyświetlić sobie te bajty szesnastkowo, bo łatwiej potem będzie sobie to zamienić na system binarny i patrzeć, w których bitach umieszczone zostały jedynki.
A wiedząc, gdzie w każdej rundzie są jedynki, będziesz wiedział, które bity zajmują które pola bitowe. Tego zaś, że po zamianie na system binarny bity liczone są od prawej strony i od zera, nie muszę Ci chyba mówić. ;-)

Tak właśnie możesz przekonać się o tym jak przeprowadzone zostaje pakowanie bitów przez gcc. :-)

Mam nadzieję, że wszystko dokładnie wyjaśniłem, a Ty i wszyscy pozostali bedziecie teraz korzystali z dobrodziejstw pól bitowych. ;-)

Napisz tu o wynikach działania programu - wklej je tu po prostu, dzięki temu i @ yak, i ja bedziemy też wiedzieć o tym, czy te pola bitowe są przydatne, czy nie.

Potem możesz sobie dla własnej ciekawości poprzerabiać tę funkcję. Możesz zmienić strukturę z polami bitowymi (np. inne szerokości pól itp.), zostawiając jednak dla każdego unsigned i zmieniając elementy tablicy bitypocz[] dla odpowiednich pól bitowych. Tych elementów musi być tyle, ile jest pól w strukturze mojebity, a wartości sobie łatwo wyliczysz ze wzoru: 2^n-1, gdzie n jest szerokością odpowiedniego pola (dla szerokości 2 zatem dany element wyniesie 3, a dla 6 - wyniesie 63). Na końcu trzeba też poprawić tą "drabinkę" switch...case, żeby uwzględniała wszystkie pola.

Powodzenia. :-)

Serdecznie Cię pozdrawiam.

PS. Nie przetestowałem nigdzie działania tej funkcji - napisałem ją od razu tutaj w poście. Nie złość się na mnie, jeśli coś będzie w niej nie tak. Po prostu popatrz dobrze i popraw. Dzięki. ;-)
_________________
Jarosław Krasuski (jaras)
^
 
 
 
druidbartek 
Expert



Telefon: DCT-3
Operator: Era
Pomógł: 39 razy
Wiek: 31
Dołączył: 13 Wrz 2005
Posty: 1006
Skąd: Wrocław
Wysłany: 2006-01-05, 13:27   

eee no ja mam problem z zastosowaniem NokiXstdout bo mam tylko 5510 a ona sie wyłącza jak sie podłącza fbusa. a jak pierwsze podłączę końcówkę a potem dopiero pod kompa to nie reaguje na klawisze :/ sprobuje jakoś inaczej wyłuskać te informacje albo może ktoś inny najlepiej na 3310. uruchamiałem w telefonie ten kod, błędów nie ma : ]
^
 
     
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Nie możesz ściągać załączników na tym forum
Dodaj temat do Ulubionych
Wersja do druku

Skocz do: