avr-gcc i operacje na strukturach określinych przez ws

May 15, 2007 11 Replies

Witam,



Mam problem z przypisaniem bajtu pod adres po przesunięciu wskaźnika. I tak mam zadeklarowane strukture: EE_STD_CODE std_code; EE_STD_CODE *p_std_code; I trochę dalej w kodzie przypisuje do wskaźnika strukturę:



p_std_code = &std_code;



I ażeby szybciej ładować dane do struktury chcę zapisywać pod poszczególne elementy struktury przrz przesunięcie wkaźnika wygryzmoliłem coś takiego ale nie działa :/ :



//uint8_t tmp3, tmp4, tmp5;



tmp4=0; for (tmp3=0;tmp3<29;tmp3++) { // struktura ma 29 bajtów (0..28) tmp5 = HexToDec(g_rs_buf[6+tmp3],g_rs_buf[7+tmp3]); // pobierz 2 znaki Hexodecymalne z bufora RS i zamień je na liczbę 8bit memcpy(p_out_code,&tmp5,1); // skopuj pod adres ze wskaźnika (do elementu struktury) odczytaną liczbę z bufora p_out_code++; // przesuń wskaźnik na kolejny element struktury tmp4 =+ 2; }



Ze wskaźnikami u mnie nie za dobrze :/ więc może być w moim toku myślenia błąd (nawet duży).


tutaj chciałeś zapewne napisać: tmp5 = HexToDec(g_rs_buf[6+tmp4],g_rs_buf[7+tmp4]);

a tutaj zgodnie z deklarację p_std_code

A tutaj sam nie wiem jaka powinna być wartość wskaźnika p_out_code: czy powinna wskazywać na następny bajt, czy na następny element tablicy elementów EE_STD_CODE. Jeśli chcę uzyskać zwiększenie o jeden bajt w takim przypadku korzystam ze wskaźnika na zmienną typu uint8.

In the darkest hour on Tue, 15 May 2007 21:26:08 +0200, Saper/nolin11 <nolin11_USUNT snipped-for-privacy@interia.pl screamed:

[1]

[2]

Struktura ma sizeof(std_code) bajtów. Tak będzie bezpieczniej. :)

To spowoduje przejście do następnej struktury, nie do następnego bajtu. Ustaw wskaźnik w [1] jako: char * p_std_code i w [2] p_std_code = (char *) &std_code.

Podsumowując:

- tak czy inaczej użyłbym '->' jak normalny czarny człowiek.

- zrób coś z tymi tmp3, tmp4 i tmp5 bo jak się na nie patrzy to zęby bolą... ;-)

In the darkest hour on Tue, 15 May 2007 21:26:08 +0200, Saper/nolin11 <nolin11_USUNT snipped-for-privacy@interia.pl screamed:

[1]

[2]

Struktura ma sizeof(std_code) bajtów. Tak będzie bezpieczniej. :)

To spowoduje przejście do następnej struktury, nie do następnego bajtu. Ustaw wskaźnik w [1] jako: char * p_std_code i w [2] p_std_code = (char *) &std_code.

Podsumowując:

- tak czy inaczej użyłbym '.' lub '->' jak normalny czarny człowiek.

- zrób coś z tymi tmp3, tmp4 i tmp5 bo jak się na nie patrzy to zęby bolą... ;-)

Artur M. Piwko schrieb:

dobrym, legalnym i dość przejrzystym rozwiązaniem jest stosowanie union. Coś w rodzaju:

typedef struct { uint8 p0; uint8 p1; uint8 p2; uint8 p3; uint8 p4; ... uint8 pxx; } tStr;

typedef union { tStr struktura; uint8 tablica[sizeof(tStr)]; } tBuba;

tBuba buba;

wtedy możesz wchodzić na np pole nr 5 poprzez buba.struktura.p5 lub buba.tablica[5];

Waldek

In the darkest hour on Wed, 16 May 2007 11:59:23 +0200, Waldemar snipped-for-privacy@zedat.fu-berlin.de> screamed:

W przypadku GCC można zrobić znacznie prościej - użyć atrybutu 'packed':

struct foobar { uint8 foo1; uint8 bar2; } __attribute__((packed));

Artur

Użytkownik "Artur M. Piwko" snipped-for-privacy@pu.kielce.pl> napisał w wiadomości news: snipped-for-privacy@beast.tu.kielce.pl...

A jak to działa? Atrybut 'packed' wymusza najciaśniejsze możliwe wyrównanie pól w pamięci, co to ma wspólnego z unią? foo1 nie zajdzie przecież na bar2...

Pozdrawiam, Przemysław Szeremiota

In the darkest hour on Wed, 16 May 2007 16:09:13 +0200, Przemysław Szeremiota snipped-for-privacy@TOTEZicpnet.pl screamed:

Atrubut packed wymusza niewypełnianie struktury bajtami paddingu, w sytuacji w której procesor wymaga wyrównania adresu pamięci dla określonego typu danych. Akurat w przypadku ośmiobitowców jest to bez znaczenia, ale pisałem generalnie. Podałem ten przykład jako alternatywę (nadal trzeba używać wskaźnika do char *), nie jako zamienni uni 1:1.

In the darkest hour on Wed, 16 May 2007 16:09:13 +0200, Przemysław Szeremiota snipped-for-privacy@TOTEZicpnet.pl screamed:

Atrubut packed wymusza niewypełnianie struktury bajtami paddingu, w sytuacji w której procesor wymaga wyrównania adresu pamięci dla określonego typu danych. Akurat w przypadku ośmiobitowców jest to bez znaczenia, ale pisałem generalnie. Podałem ten przykład jako modyfikację oryginalnej metody autora (nadal trzeba używać wskaźnika do char *), nie jako zamiennik uni 1:1.

Użytkownik "Saper/nolin11" <nolin11_USUNT snipped-for-privacy@interia.pl napisał w wiadomości news:f2d1fn$mks$ snipped-for-privacy@news.dialog.net.pl...

Jeśli miało być _szybciej_, to nie wyszło :-).

Sorry, ale wywołanie memcpy() dla jednego bajta to trochę przegięcie -- nie wystarczy przypisać (((char *)p_out_code)[tmp3] = tmp5;)? Do tego równolegle do licznika pętli masz inkrementację wskaźnika, zbędną przy powyższym przypisaniu, a to ona rozwala Ci przesunięcia wskaźnika :-). Inne błędy wytknęli już koledzy :-).

Pozdrawiam, Przemysław Szeremiota

Użytkownik "Artur M. Piwko" snipped-for-privacy@pu.kielce.pl> napisał w wiadomości news: snipped-for-privacy@beast.tu.kielce.pl...

Zgadza się,

Aa, oryginalnej metody autora -- dobrze, bo już zacząłem się marszczyć :-).

Pozdrawiam, Przemek Szeremiota

In the darkest hour on Wed, 16 May 2007 16:38:25 +0200, Przemysław Szeremiota snipped-for-privacy@TOTEZicpnet.pl screamed:

Czasami w sigu losuje mi się taki (super;) "oneliner":

int i ; memset( &i, 0, sizeof(int) );

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required