PODSTAW PROGRAMOWANIA WYKŁAD 6 WSKAŹNIKI Wskaźnik
Transkrypt
PODSTAW PROGRAMOWANIA WYKŁAD 6 WSKAŹNIKI Wskaźnik
PODSTAW PROGRAMOWANIA WYKŁAD 6 WSKAŹNIKI Wskaźnik jest zmienną, która zawiera adres (wskazanie) początku dowolnego obszaru w pamięci komputera, (np. może być to adres obszaru danych lub adres kodu programu) Ogólna postać definicji wskaźnika: typ_danych identyfikator wskaźnika ; Podstawowe zastosowania wskaźników to: 1. przekazywanie przez wskaźnik zmiennej jako argumentu funkcji, 2. dynamiczny przydział pamięci, 3. operacje arytmetyczne na wskaźnikach. 4. Wskaźniki używane do dostępu do tablic 1. przekazywanie przez wskaźnik zmiennej jako argumentu funkcji, #include <stdio.h> int wartosc( int x ); void wskaznik (int *x); int main() { int x = 1; int y; y = wartosc(x); printf("Wartosc x po wywolaniu funkcji wartosc: %d\n", x); wskaznik(&x); printf("Wartosc x po wywolaniu funkcji wskaznik: %d\n", x); return 0; } int wartosc( int x ) { x++; return x; } void wskaznik (int *x) { (*x)++; } #include<stdio.h> #include<stdlib.h> void f1(int x); void f2(int* x); void f3(int** x); void f4(int& x); int main() { int i,j,*k,*l,*m,n; k=(int*)malloc(sizeof(int)); l=(int*)malloc(sizeof(int)); m=(int*)malloc(sizeof(int)); i=j=*k=*l=*m=n=2; (*m)--; f1(i); f2(&j); f2(k); f3(&l); f4(n); printf("%d\n%d\n%d\n%d\n%d",i,j,*k,*l,n); free(k); free(l); free(m); return 0; } void f1(int x) { x--; return; } void f2(int* x) { (*x)++; return; } void f3(int** x) { *x+=sizeof(int); return; } void f4(int& x) { x*=2; return; } 2. dynamiczny przydział pamięci, malloc() (stdlib.h) – przydział n bajtów pamięci void * memcpy ( void * destination, const void * source, size_t num ); /* memcpy example */ #include <stdio.h> #include <string.h> struct { char name[40]; int age; } person, person_copy; int main () { char myname[] = "Pierre de Fermat"; /* using memcpy to copy string: */ memcpy ( person.name, myname, strlen(myname)+1 ); person.age = 46; /* using memcpy to copy structure: */ memcpy ( &person_copy, &person, sizeof(person) ); printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age ); return 0; } int memcmp ( const void * ptr1, const void * ptr2, size_t num ); /* memcmp example */ #include <stdio.h> #include <string.h> int main () { char buffer1[] = "DWgaOtP12df0"; char buffer2[] = "DWGAOTP12DF0"; int n; n=memcmp ( buffer1, buffer2, sizeof(buffer1) ); if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2); else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2); else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2); return 0; } void * memset ( void * ptr, int value, size_t num ); void * memmove ( void * destination, const void * source, size_t num ); memmove example */ #include <stdio.h> #include <string.h> int main () { char str[] = "memmove can be very useful......"; memmove (str+20,str+15,11); puts (str); return 0; } Ze wskaźnikami i adresami związane są dwa operatory: operator referencji & zwracający adres zmiennej podanej po prawej stronie tego operatora. operator dereferencji identyfikujący obszar wskazywany przez wskaźnik podany po prawej stronie tego operatora. int liczba ; int wskaźnik ; wskaznik = &liczba; wskaźnik = 10; // przypisanie zmiennej wskaźnik // adresu zmiennej liczba // przypisanie 10 zawartości zmiennej // wskazywanej przez wskaźnik // tutaj równoważne liczba = 10 Arytmetyka wskaźników Na wskaźnikach mogą być wykonywane następujące operacje: * przypisania ( = ) wsk = wskaznik_zmiennej_lub_obszaru_pamięci ; (w przypadku niezgodności typów konieczne jest dokonanie konwersji typu) * operacje porównania ( ==, !=, <, >, <=, >= ): wsk_1 == wsk_2 // sprawdzenie czy zmienne zawierają te same adresy wsk_1 < wsk_2 // czy zmienna wsk_1 zawiera adres mniejszy // od adresu zawartego w zmiennej wsk_2 * operacje powiększania lub pomniejszania wskaźnika ( +, -, ++, --, +=, -= ) o liczbę całkowitą (tylko dla wskaźników zdefiniowanych) - powiększenie (pomniejszenie) wskaźnika o wartość N powoduje wyznaczenie adresu przesuniętego o: N - sizeof( typ_zmiennej_wskazywanej ) //Program 4 #include <stdio.h> void main() { char i[3]={5,6,7},*wskaznik; wskaznik=&(i[0]); *wskaznik/=2; wskaznik++; (*wskaznik)+=9; wskaznik++; (*wskaznik)*=13; printf("%d %d %d",i[0],i[1],i[2]); return; } #include <stdio.h> void main() { char i[3]={5,6,7},*wskaznik; wskaznik=&(i[0]); *wskaznik/=2; wskaznik++; (*wskaznik)+=9; wskaznik++; (*wskaznik)*=13; printf("%d %d %d",i[0],i[1],i[2]); return; } Najczęściej arytmetykę wskaźników stosuje się do dynamicznych odpowiedników tablic . Najczęstszym i najważniejszym zastosowaniem operacji arytmetycznych jest przeglądanie (iterowanie) struktur danych — w szczególności tablic/łańcuchów znaków. Wykorzystuje się do tego celu głównie operator inkrementacji ++. Do wskaźników można też dodawać dowolną liczbę całkowitą, a także odejmować od nich dowolną liczbę całkowitą. Dla przykładu zdefiniujemy wskaźnik, do którego przypiszemy adres początku tablicy. int *wskaznik = tablica; // — trzeba pamiętać, że zapis tablica jest równoważny z &tablica[0], czyli oznacza adres jej początku #include <stdio.h> #include <string.h> void odwrocenie (char *s); int main() { char ciag_znakow[20] = "Rychu ma bimber"; odwrocenie(ciag_znakow); printf("Ciag znakow po odwroceniu: %s\n", ciag_znakow); return 0; } void odwrocenie(char *s) { char *wsk = s + strlen(s)-1; char temp; for (;wsk>s;wsk--,s++) { temp = *s; *s = *wsk; *wsk = temp; } }