mario2015 napisał(a):
Jeśli dobrze to zrozumiałem, to nadal nie rozumiem po co tak komplikować program, skoro są łatwiejsze zapisy kodu, chociażby w linijkach od 23 do 31
chyba że ma to znaczenie nie wiem, może w jakichś funkcjach?
Rozumiem, że pytasz o sens stosowania wskaźników?
Wyobraź sobie zdefiniowanie tablicy zawierającej nazwy elementów menu (dla uproszczenia dwie):
- "Ustawienia transmisji"
- "PWM"
Można przy użyciu tablicy wielowymiarowej, ale wtedy musisz zadeklarować jeden z jej wymiarów na wartość 22, ponieważ taka jest długość najdłuższej nazwy:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Stosując wskaźniki można zrobić tak:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
zyskując 14 bajtów (przy większej ilości nazw o zróżnicowanych długościach ten zysk może być dużo większy).
Inna sytuacja, przekazywanie zmiennej do funkcji poprzez wskaźnik:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Może to być np. przydatne, jeśli w jednym z modułów programu mamy zdefiniowaną zmienną lokalną, niewidoczną i niedostępną w innych modułach, ale w jakichś szczególnych okolicznościach chcemy ją udostępnić dla innego modułu. Można to właśnie zrobić, przekazując do innego modułu wskaźnik do tej zmiennej jako argument funkcji.
Można też np. za pomocą argumentu funkcji przekazać z jednego modułu do innego modułu adres bufora (tablicy), do którego ten drugi ma przekopiować dane (np. odebrane wcześniej przez UART).
Wskaźniki mogą być także bardzo przydatne, jeśli przykładowo chcemy do funkcji przekazać jako argument adres jakiegoś portu (lub innego rejestru IO):
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
To oczywiście bardzo proste przykłady i może się wydawać, że nie mają większego sensu, ale naprawdę mogą okazać się bardzo przydatne, szczególnie w większych projektach podzielonych na moduły. Można wtedy na przykład za pomocą wskaźników ograniczyć lub zlikwidować konieczność używania zmiennych globalnych widocznych w całym projekcie (stosowanie takich zmiennych jest raczej złą praktyką).
No i oczywiście jednym z podstawowych sposobów wykorzystania wskaźników, o czym pisali już koledzy wcześniej), jest alternatywny (w stosunku do indeksowania) dostęp do elementów tablicy. W tej chwili wydaje Ci się to może trochę mniej czytelne rozwiązanie (nazwałeś to komplikowaniem), ale kiedy dobrze opanujesz temat, to może zmienisz zdanie. Przykładowo funkcja wyświetlająca ciąg znaków (stosując wskaźniki) wyglądałaby jakoś tak (zakładamy, że
lcd_putc() wyświetla pojedynczy znak):
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Jak wyglądałaby Twoja z odczytem za pomocą indeksu tablicy?
Wskaźniki są też stosowane przez funkcje z biblioteki standardowej, takie jak np.
memcpy(), gdzie jako argumenty podajesz wskaźnik do źródła, wskaźnik do celu i rozmiar. Dzięki wskaźnikom (tutaj jest to specjalny typ wskaźnika -
void *) funkcja ta może kopiować zmienne praktycznie dowolnego typu, nie tylko tablice, ale też int, float, double, char czy też różne struktury (zawierające elementy różnych typów). Bez wskaźników stworzenie takiej uniwersalnej funkcji byłoby praktycznie niemożliwe.
Nie piszę tu o dynamicznej alokacji pamięci, choć to jeden z podstawowych sposobów użycia wskaźników, ponieważ biorąc pod uwagę stosunkowo małe zasoby pamięci RAM w mikrokontrolerach AVR przy jednoczesnym braku MMU, jej nieumiejętne użycie może dać więcej szkody niż pożytku. Dynamiczna alokacja pamięci powinna być używana ze świadomością ewentualnych konsekwencji i ostrożnie, dlatego nie polecam jej mniej zaawansowanym programistom (przynajmniej na początku poznawania wskaźników).
Trudno tak na poczekaniu wymyślić jakiś stosunkowo prosty i jednocześnie sensowny przykład użycia wskaźników, dlatego skupiłem się na pokazaniu różnic pomiędzy dostępem do zmiennej poprzez wskaźnik a dostępem bezpośrednim. Znając różnice, może sam znajdziesz zastosowanie.