Wskaźnik do zmiennej/stałej const

Tu możesz pisać o swoich problemach z pisaniem programów w języku C dla AVR.
Awatar użytkownika
danielos
Newb
Newb
Posty: 69
Rejestracja: sobota 02 sty 2016, 15:06
Lokalizacja: Pawłowice, Silesia.
Kontaktowanie:

Wskaźnik do zmiennej/stałej const

Postautor: danielos » sobota 09 kwie 2016, 13:35

Witam.

Problem/pytanie które przedstawię, wynika z zastosowania nowego toolchaina z ATmela (wcześniej na winAVR wszystko działało bez problemów)

Mam zdefiniowane takie zmienne (TD_MENU moja struktura):

Kod: Zaznacz cały

extern const TD_MENU main_menu[MENU_NR_MAIN] PROGMEM;
extern const TD_MENU conf_menu[MENU_NR_CONF] PROGMEM;
extern const TD_MENU out_menu[MENU_NR_OUT] PROGMEM;


W programie przypisuję do innej zmiennej, wskaźnik do aktualnego wyświetlanego menu w taki oto sposób:

Kod: Zaznacz cały

M_tab_kierunku[poziom_menu].wsk_menu = (void *)main_menu;


:?: Dla winAVR program dobrze działał bez tego rzutowania, ale jak zmieniłem toolchaina na atmelowskiego to pojawiły się znane już błędy z danymi umiejscowionymi w pamięci FLASH. Po dodaniu rzutowania void błąd zniknął.
Czy jest to prawidłowe i mogę tak to stosować, czy muszę zmienić jednak typ zmiennej do której przypisywany jest wskaźnik (jeżeli dobrze rozumiem to musiałbym dodać specyfikator const dla typu wskaźnika)? :?:

Błąd jaki miałem bez tego rzutowania, brzmiał:

Kod: Zaznacz cały

assignment discards 'const' qualifier from pointer target type [enabled by default]


I jeszcze takie wyjaśnienie co do tablicy kierunku:

Kod: Zaznacz cały

TD_TRACE M_tab_kierunku[MAX_POZIOM];      //zapis drogi szkodnika po menu


a struktura TD_TRACE, wygląda tak:

Kod: Zaznacz cały

typedef struct{
   TD_MENU *wsk_menu;            //wskaźnik do aktywnego menu
   uint8_t il_menu;            //ile dane menu ma pozycji
   uint8_t pozycja_menu;         //pozycja wybranego następnego menu
}TD_TRACE;
Można wszystko osiągnąć, wystarczy chcieć.

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: Wskaźnik do zmiennej/stałej const

Postautor: Antystatyczny » sobota 09 kwie 2016, 15:40

przypuszczam, że wskaźnik wsk_menu nie jest typu const TD_MENU* i dlatego kompilator odrzuca modyfikator const przy zadeklarowanej przez Ciebie tablicy struktur main_menu[MENU_NR_MAIN]. Tam jeszcze widzę, że dochodzi odczyt z flash, więc nie mam pewności, czy sama zmiana typu wskaźnika wystarczy... Gdybyś nadal miał z tym problemy, to zachęcam do wklejenia nieco większego kawałka kodu. Głównie deklaracje

Pozdrawiam
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: Wskaźnik do zmiennej/stałej const

Postautor: Antystatyczny » sobota 09 kwie 2016, 15:44

hhmm...tak, zmień to:

Kod: Zaznacz cały

 TD_MENU *wsk_menu;            //wskaźnik do aktywnego menu

na to:

Kod: Zaznacz cały

 const  TD_MENU *wsk_menu;            //wskaźnik do aktywnego menu

i powinno być git
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

Awatar użytkownika
danielos
Newb
Newb
Posty: 69
Rejestracja: sobota 02 sty 2016, 15:06
Lokalizacja: Pawłowice, Silesia.
Kontaktowanie:

Re: Wskaźnik do zmiennej/stałej const

Postautor: danielos » sobota 09 kwie 2016, 16:19

Tak jak wspominałem, zastosowanie rzutowania (void *) powoduje, że błąd znika, a program jak na razie działa.
Bardziej mi się rozchodzi czy można takie rzutowanie stosować i nie spowoduje to w przyszłości problemów w działaniu programu.

Antystatyczny pisze:hhmm...tak, zmień to:

Kod: Zaznacz cały

 TD_MENU *wsk_menu;            //wskaźnik do aktywnego menu

na to:

Kod: Zaznacz cały

 const  TD_MENU *wsk_menu;            //wskaźnik do aktywnego menu

i powinno być git


Tak, zmiana ta niweluje problem (jednak też dobrze myślałem).
Pojawiają się dodatkowe warningi w innych plikach, gdzie wykorzystuję ten wskaźnik. Będę musiał zrobić chyba większy update programu.

Jednakże, jeżeli rzutowanie które zastosowałem będę mógł bez ewentualnych problemów stosować, to wolę tą opcję, bo niweluje konieczność modyfikacji reszty programu.
Można wszystko osiągnąć, wystarczy chcieć.

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: Wskaźnik do zmiennej/stałej const

Postautor: Antystatyczny » sobota 09 kwie 2016, 16:22

Korzystając z (void *) rzutujesz na typ "byle jaki" i zasadniczo można z tego korzystać i nawet w niektórych sytuacjach jest to bardzo wygodne, bo możesz do funkcji przekazać adres "byle jakiej" struktury, a dopiero wewnątrz funkcji sobie przerzutować na co się chce. Nie nadużywałbym tego, bo potem można się pogubić w programie... Widząc przyjmowany typ mamy jako takie rozeznanie, czego oczekuje od nas funkcja, a przy (void *) możemy przekazać wszystko.
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

Awatar użytkownika
danielos
Newb
Newb
Posty: 69
Rejestracja: sobota 02 sty 2016, 15:06
Lokalizacja: Pawłowice, Silesia.
Kontaktowanie:

Re: Wskaźnik do zmiennej/stałej const

Postautor: danielos » sobota 09 kwie 2016, 16:40

W moim przypadku różnica w typie zmiennej polega na specyfikatorze const.

Zobaczę, czy zastosowanie const nie spowoduje gdzieś w programie błędu, którego w łatwy sposób nie będę potrafił usunąć. Jeżeli wszystko przebiegnie pomyślnie to zostawię to const przed nazwą zmiennej, a jak nie to będę rzutował, z wykorzystaniem void.

Jeszcze takie pytanko jedno, bo jakąś blokadę w głowie mam w zrozumienie wszystkiego do końca ze specyfikatorem const.

Otóż, zastosowanie const, powoduje że zmienna jest stałą, która nie może być zmieniana w programie - można z niej tylko odczytywać. Aby zrobić wskaźnik na stałą musi on też posiadać specyfikator const, czyli że też jest wartością stałą i nie może być zmieniany w trakcie działania programu? Czy jednak może być zmieniany (oczywiście wskaźnik), np. na inną/kolejną stałą?

Jakaś zębatka w głowie nie umie przeskoczyć, żeby zrozumieć tą zawiłość związaną z const i wskaźnikiem do const.

Dzięki za pomoc.
Można wszystko osiągnąć, wystarczy chcieć.

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: Wskaźnik do zmiennej/stałej const

Postautor: Antystatyczny » sobota 09 kwie 2016, 16:49

Nie, nie... Deklarując wskaźnik np. const char *ptr; mówisz kompilatorowi, że wskaźnik ptr będzie wskazywał na jakąś zmienną typu const char. Sam adres wskaźnika możesz zmieniać, ale zawartości, na jaką wskazuje, nie. :)

Oczywiście można zadeklarować tak: const char const *ptr; i wtedy nie będziesz mógł zmienić ani adresu, ani zawartości. Taki betonowy wskaźnik... Taki wskaźnik trzeba natychmiast inicjalizować, bo jak potem z niego skorzystać? :)
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.

Awatar użytkownika
danielos
Newb
Newb
Posty: 69
Rejestracja: sobota 02 sty 2016, 15:06
Lokalizacja: Pawłowice, Silesia.
Kontaktowanie:

Re: Wskaźnik do zmiennej/stałej const

Postautor: danielos » niedziela 10 kwie 2016, 07:30

Acha, takie klocki.

Dzięki wielkie za wyjaśnienie i to bardzo jasne wyjaśnienie - w końcu zębatki w głowie u mnie zaskoczyły.

Masz u mnie duże piwo ;)
Można wszystko osiągnąć, wystarczy chcieć.

Awatar użytkownika
mokrowski
User
User
Posty: 190
Rejestracja: czwartek 08 paź 2015, 20:50
Lokalizacja: Tam gdzie Centymetro

Re: Wskaźnik do zmiennej/stałej const

Postautor: mokrowski » poniedziałek 11 kwie 2016, 16:03

Ino const przed gwiazdką powinno być aby był betonowy. const przed i po char znaczy to samo. Tak więc betonowy to:
const char * const ptr;
.. a to samo to:
char const * const ptr; (także betonowy)
A i jeszcze, czytaj od prawej czyli np. dla typu:
const char * volatile ptr;

ptr jest ulotnym wskaźnikiem na znak stały :-)
,,Myślenie nie jest łatwe, ale można się do niego przyzwyczaić" - Alan Alexander Milne: Kubuś Puchatek

Awatar użytkownika
Antystatyczny
Geek
Geek
Posty: 1168
Rejestracja: czwartek 03 wrz 2015, 22:02

Re: Wskaźnik do zmiennej/stałej const

Postautor: Antystatyczny » poniedziałek 11 kwie 2016, 17:04

Tak, tak...pozajączkowała mi się kolejność, bo napisałem z pamięci, nie sprawdzając w kodzie. Miało być const char *const ptr;
"The true sign of intelligence is not knowledge but imagination" Albert Einstein.


Wróć do „Programowanie AVR w C”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 3 gości