Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 12 lis 2024, o 05:23


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 9 ] 
Autor Wiadomość
PostNapisane: 5 sty 2022, o 16:21 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 05 sty 2018
Posty: 14
Pomógł: 0

Chcę powitać wszystkich. Cześć.
Odświeżę trochę wątek wskaźników, ale w innej kwestii. Wskaźniki, piękna rzecz, ale... Mam problem z deklaracją wskaźników. Mówi się, że deklaracja (typ) wskaźnika powinna być taka sama jak deklaracja (typ) zmiennej, której adres wskazuje (mimo, że w avr 8 bit zawsze wskaźnik będzie dwubajtowy - wynika to z adresacji) to dla:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Chyba do tej pory dobrze myślę.

I teraz. Rozumiem to, że typ wskaźnika musi być taki jak typ zmiennej, ponieważ przy operacji odwrotnej czyli zapisu do komórki pod adres wskaznik_zmiennej_x jakiejś nowej wartości np. xx typ jej musi być zgodny z typem zmiennej x (w moim przykładzie 4 bajtowej) z której pobraliśmy adres żeby "zmienna się tam zmieściła".

Ale wymyśliłem sobie, że na port PORTB chcę wysłać najmłodszy bajt zmiennej unit32_t czyli x, a na port PORTD najstarszy bajt zmiennej x. I tutaj okazuje się, ze dla deklaracji wskaźnika dla zmiennej x jako unit32_t mam z tym problem, a dla deklaracji wskaźnika jako unit8_t dla tej zmiennej unit32_t wszystko działa dobrze. Ale najprościej będzie chyba pokazać część programu.

Dla wersji uint32_t *WSK_PORTB;
----------------------------------------------------------

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


-----------------------------------------------------------
Na POTRB wysłana prawidłowa wartość, na PORTD jakaś przypadkowa wartość.

Teraz dla wersji uint8_t *WSK_PORTB;
------------------------------------------------------------
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

---------------------------------------------------------
Na POTRB wysłana prawidłowa wartość i na PORTD też przypadkowa wartość.

Czy można tak jak powyżej deklarować wskaźnik o typie innym niż zmienna, której dotyczy. Na razie ta część programu działa dobrze, ale może w jakiejś sytuacji coś pójdzie nie tak.
Z góry dziękuję za sugestie.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 sty 2022, o 17:40 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 06 mar 2015
Posty: 315
Lokalizacja: Czerwionka-Leszczyny
Pomógł: 22

Poczytaj o przesunięciach bitowych i obejrzyj przy okazji te poradniki zaczynając od tego:
https://www.youtube.com/watch?v=V83w0pu7MVo&t=2s

_________________
http://www.avrboss.pl



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 sty 2022, o 18:01 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27308
Lokalizacja: Szczecin
Pomógł: 1041

nowy_stary napisał(a):
PORTD = *(WSK_PORTB+3);

W pierwszym przypadku gdy twój wskaźnik ma typ uint32_t robisz masakrę bo pominąłeś to jak działa arytmetyka wskaźników. Operacja WSK_PORT+3 powoduje przesunięcie i odczyt o fizycznie 12 bajtów dalej. Zajrzyj proszę do Bluebooka do wskaźników są fajne przykłady jak działa arytmetyka wskaźników.

W drugim przypadku gdy już twój *WSK_PORTB jest typu uint8_t powinno być dobrze - ale widać że kod piszesz niedbale - bo na pewno zgłaszają ci się warningi - chociażby podczas operacji przypisania

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


albo może działasz w kocim Atmel Studio w którym masz wyłączone warningi - oczywiście to nie jest powodem błędu o którym piszesz może on leżeć gdzie indziej ale dobrze byłoby zobaczyć PORZĄDNY kod testowy i dowiedzieć się na czym to testujesz - bo skoro wysyłasz sobie wartość na PORTD to jak to odczytujesz - masz podłączone 8 diod LED ? Nie prościej albo wysyłać sobie wartość liczbową na UART albo podłączyć byle wyświetlacz LCD i wyświetlać sobie zamiast takie karkołomne testy robić

Napisz tą drugą wersję kodu poprawnie i pokaż - ale tak, żeby żaden warning podczas kompilacji się nie pojawiał. Bo oczywiście druga wersja kodu powinna działać poprawnie - tu arytmetyka WSK_PORTB+3 zadziała zgodnie z twoim założeniem - na PORTD powinna być podana wartość czwartego bajtu zmiennej x

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 sty 2022, o 18:55 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 05 sty 2018
Posty: 14
Pomógł: 0

Dzięki za szybką reakcję.
mirekk36 napisał(a):
W pierwszym przypadku gdy twój wskaźnik ma typ uint32_t robisz masakrę bo pominąłeś to jak działa arytmetyka wskaźników. Operacja WSK_PORT+3 powoduje przesunięcie i odczyt o fizycznie 12 bajtów dalej.

OK, to pomyłka przy przepisywaniu. Miało być :
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


ale i tak nie działa dobrze. A ja chciałem wymusić przesuniecie się na ostatni bajt zmiennej uint32_t zmieniając typ wskaźnika. Taki mój pomysł. Warning podczas kompilacji oczywiście się pojawia dlatego powstał wątek, bo działa dobrze, ale jest warning.

mirekk36 napisał(a):
albo może działasz w kocim Atmel Studio


Nie żadne Atmel Studio - 100% Mirku Twoja szkoła i sprzęt.

mirekk36 napisał(a):
Napisz tą drugą wersję kodu poprawnie i pokaż - ale tak, żeby żaden warning podczas kompilacji się nie pojawiał. Bo oczywiście druga wersja kodu powinna działać poprawnie - tu arytmetyka WSK_PORTB+3 zadziała zgodnie z twoim założeniem - na PORTD powinna być podana wartość czwartego bajtu zmiennej x


Dobrze, ale rozumiem, że mam przyzwolenie na to, żeby stosować typ uint8 dla wskaźnika dla zmiennej uint32.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 sty 2022, o 19:20 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27308
Lokalizacja: Szczecin
Pomógł: 1041

nowy_stary napisał(a):
OK, to pomyłka przy przepisywaniu. Miało być :

to i tak źle - przecież jeśli wskaźnik jest typu uint32_t to wsk+1 przesunie ci się fizycznie o 4 bajty rozumiesz ? o rozmiar typu - a typ uint32_t to 4 bajty

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 sty 2022, o 19:44 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 05 sty 2018
Posty: 14
Pomógł: 0

Dokładnie tak. Wiem to od początku. Rozumiem rozkład bajtów itd. Dlatego zmieniłem typ wskaźnika żeby poruszać się co bajt, a nie tyle bajtów co wynika z typu wskaźnika zmiennej 4 bajtowej. Teraz tylko próbuję dociec czy używanie typu wskaźnika innego niż typ zmiennej, której wskaźnik dotyczy jest właściwe. Chyba nie bo eclipsik się buntuje wysyłając warning. Ale kurcze efekt jest prawidłowy po kompilacji. Chyba, że jest inny sposób na obejście tego, żeby używając wskaźnik zmiennej 4 bajtowej poruszać się w pamięci o jeden bajt. O to mi głównie chodzi.
Przecież nie dodam do wskaźnika zmiennej 4 bajtowej 0,25 żeby znaleźć się na najmłodszym bajcie zmiennej :).



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 sty 2022, o 20:05 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27308
Lokalizacja: Szczecin
Pomógł: 1041

nowy_stary napisał(a):
eraz tylko próbuję dociec czy używanie typu wskaźnika innego niż typ zmiennej, której wskaźnik dotyczy jest właściwe. Chyba nie bo eclipsik się buntuje wysyłając warning.

a co ma eclipsik który jest tylko zwykłym edytorem tekstu do kodu źródłowego w C ? NIC

Warninga to masz od kompilatora i trzeba się go pozbyć robiąc jawne rzutowanie i o tym też było i jest w Bluebooku

u ciebie musi być

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


------------------------ [ Dodano po: kilkunastu sekundach ]

nowy_stary napisał(a):
Chyba, że jest inny sposób na obejście

A po co obchodzić coś co się załatwia właśnie w ten sposób

------------------------ [ Dodano po: 1 minucie ]

po to są właśnie wskaźniki


Autor postu otrzymał pochwałę

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 sty 2022, o 20:18 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 05 sty 2018
Posty: 14
Pomógł: 0

Dzięki zatrybiłem. Wystarczyło na początku napisać jawne... :)
Tak od kompilatora.
Jeszcze raz dzięki. Może ta dyskusja komuś też pomoże.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 sty 2022, o 11:02 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 29 lis 2019
Posty: 145
Pomógł: 37

To co tu robisz ze wskaźnikiem ma swoją nazwę: strict aliasing violation. Efekt tych dziań jest nieokreślony (undefined behaviour). Dalej - arytmetyka wskaźników ma sens tylko w ramach jednej tablicy. NIE ma sensu w przypadku niezależnych zmiennych. Kolejne UB.
Także, rozdział o wskaźnikach do powtórki.

_________________
Think for yourself and question authority.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 9 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 0 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
cron
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO