Prezentacja programu PowerPoint
Transkrypt
Prezentacja programu PowerPoint
Katedra Elektrotechniki Teoretycznej i Informatyki wykład 8 - sem.III Dr inż. M. Czyżak Język ANSI C i C++ – dynamiczna alokacja pamięci cz. I W językach C i C++ istnieją zasadniczo dwa rodzaje zmiennych: - zmienne zwykłe definiowane w funkcji main() lub na zewnątrz wszystkich funkcji lub w pewnym bloku. Każda zmienna tego rodzaju posiada swoją nazwę oraz określony typ. - zmienne dynamiczne tworzone i usuwane w trakcie działania programu; taki sposób przydzielania pamięci zwany jest alokacją w trakcie działania programu (ang. run-time allocation). Zmienne te nie posiadają nazw, znane są wyłącznie adresy przydzielonej im pamięci ( wskaźniki do tej pamięci). Do przydzielania pamięci zmiennym dynamicznym służą w ANSI C funkcje malloc i calloc. Do usuwania zmiennych dynamicznych stosuje się funkcję free. Język ANSI C – dynamiczna alokacja pamięci Funkcje malloc i calloc (stdlib.h) Każda z tych funkcji alokuje przydziela pamięć i zwraca adres tej pamięci (wskaźnik do tej pamięci). Rozmiar przydzielanej pamięci nie musi być znany podczas kompilacji. Funkcja malloc Nagłówek funkcji tej ma postać następującą: void * malloc (int); Funkcja malloc oczekuje, jako swojego argumentu, liczby bajtów, które mają być przydzielone w danym wywołaniu funkcji. Jeżeli przydzielenie pamięci jest możliwe, funkcja zwraca wskaźnik do tej pamięci, jeśli nie, funkcja zwraca NULL (zerowy wskaźnik). Zwracany wskaźnik jest typu void*, czyli jest to wskaźnik do void. Język ANSI C – dynamiczna alokacja pamięci Wskaźnik ten musi być przekształcony (przez rzutowanie) na wskaźnik do żądanego typu. Język C gwarantuje, że wskaźnik do void może być przekształcony na wskaźnik do każdego innego typu. Język ANSI C – dynamiczna alokacja pamięci Przykład. Zastosowanie funkcji malloc do alokacji pamięci dla zmiennej dynamicznej typu int. #include <stdio.h> #include<stdlib.h> int main() { int *ptr; ptr=(int*) malloc( sizeof(int)); if (ptr= = NULL){ printf("\n Przydzielenie pamięci nie było możliwe"); system("pause");return 1;} printf(" Podaj wartosc :"); scanf("%d", ptr); printf("\n Wartosc to :%d", *ptr); free(ptr); system("pause"); return 0; } Język ANSI C – dynamiczna alokacja pamięci Funkcja calloc Nagłówek funkcji tej ma postać następującą: void * calloc (int,int); Funkcja calloc oczekuje dwóch argumentów typu int. Pierwszy argument oznacza liczbę bloków pamięci, które mają zostać przydzielone, a drugi rozmiar pojedynczego bloku. Funkcja zwraca wskaźnik do pierwszego bloku. Wskaźnik ten jest typu void* i musi być rzutowany na wskaźnik do wymaganego typu. Język ANSI C – dynamiczna alokacja pamięci Przykład. Zastosowanie funkcji calloc do alokacji pamięci dla tablicy liczb typu int. #include <stdio.h> int main() { int *ptr,i; ptr=(int *)calloc(5, sizeof(int)); for (i=0;i<5;i++) { printf("\n Podaj element %d", i); scanf("%d", ptr++); } ptr=ptr-5;//cofnięcie wskaźnika na początek tablicy for (i=0;i<5;i++) { printf("\n Element [%d]=%d", i,*ptr++); ptr=ptr-5; free(ptr); system("pause"); return 0; } Język ANSI C – dynamiczna alokacja pamięci Przykład. Dynamiczna alokacja tablicy z użyciem funkcji zwracającej wskaźnik. #include <stdio.h> #include <stdlib.h> int* wczytTab(int n); int main(int argc, char **argv) { int *pa,i,n=5; pa=wczytTab(5); for (i=0;i<n;i++) printf("\n Element[%d]=%d",i, *pa++); pa=pa-5; free(pa); system("pause");} Język ANSI C – dynamiczna alokacja pamięci Przykład cz. II ( ciąg dalszy programu) ( definicja funkcji zwracającej wskaźnik do wczytanej tablicy) int* wczytTab(int n) { int i,*px; px=(int*) malloc(n*sizeof(int)); for (i=0;i<n;i++) { printf("\n Podaj element[%d]=",i); scanf("%d",px++); } px=px-n;// wskaźnik jest cofany o n elementów do tyłu, // tak aby wskazywał na początek obszaru pamięci // alokowanego dla tablicy return px; // wskaźnik jest zwracany (wysyłany do funkcji) // która wywołała funkcję wczytTab, w tym przypadku // do funkcji main() } Język ANSI C – dynamiczna alokacja pamięci Przykład. Program wczytujący tablicę dwuwymiarową przy użyciu wskaźnika, do funkcji przekazywany jest wskaźnik do pierwszego elementu tablicy dwuwymiarowej. #include <stdio.h> #include <stdlib.h> //Do funkcji przekazywany jest wskaźnik do pierwszego elementu //tablicy dwuwymiarowej oraz liczba wierszy i liczba kolumn. void wczyt(int *px, int w, int k) { int i,j; for (i=0;i<w;i++) for (j=0;j<k;j++) { printf("\n Podaj element [%d][%d]=",i,j); scanf("%d",px++); } } Język ANSI C – dynamiczna alokacja pamięci Przykład c.d. zastosowanie funkcji wczyt do wczytania tablicy dwuwymiarowej 3x3. int main() { int x[3][3]; int *px; int i,j; system("cls"); px=&x[0][0]; wczyt(px,3,3); for (i=0;i<3;i++) for (j=0;j<3;j++) printf("\n element [%d][%d]=%d",i ,j, x[i][j]); system("pause"); return 0; } Język ANSI C – dynamiczna alokacja pamięci Przykład. Funkcja wczytD alokuje pamięć dla tablicy dwuwymiarowej o zadanej liczbie kolumn i zadanej liczbie wierszy, wczytuje tablicę i zwraca wskaźnik do jej pierwszego elementu. int *wczytD(int w, int k) { int *px; int i,j; px=(int*)calloc(w*k,sizeof(int)); for (i=0;i<w;i++) for (j=0;j<k;j++) { printf("\n Podaj element [%d][%d]=",i,j); scanf("%d",px++); } px=px-w*k; return px; } Język ANSI C – dynamiczna alokacja pamięci Przykład c.d. zastosowanie funkcji wczytD do wczytania tablicy dwuwymiarowej 3x3. int main() { int *py,i,j; py=wczytD(3,3); for (i=0;i<3;i++) for (j=0;j<3;j++) printf("\n element [%d][%d]=%d",i,j,*py++); py=py-9; free(py); system("pause"); return 0;} Język ANSI C – dynamiczna alokacja pamięci Alokacja dynamiczna tablic dwuwymiarowych Alokację dynamiczną w języku C można dla takich tablic zrealizować zasadniczo stosując jeden z dwóch sposobów: - tablicę wskaźników o postaci *wskaznik[ ] - wskaźnik do tablicy o postaci (*wskaznik)[] Przykład. Tablica 5 wskaźników do int. int *ptab[5]; Przykład. Wskaźnik do tablicy 5-elementowej o elementach typu int. int (*wsktab)[5]; Język ANSI C – wskaźniki Przykład. Sprawdzanie efektu zwiększania wskaźnika do tablicy dwuwymiarowej. #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int (*pa)[5];// definicja wskaźnika do tablicy dwuwymiarowej pa=calloc(5,sizeof(int)); printf("\n adres1=%d", pa); printf("\n adres2=%d", pa+1); printf("\n"); system("PAUSE"); return 0; } // Wynik działania programu adres1=4007136 adres1=4007156 // Wskaźnik przesuwa się o 20 bajtów( 5*sizeof(int)) Język ANSI C – dynamiczna alokacja pamięci Alokacja dynamiczna tablic dwuwymiarowych w języku C W pierwszym przypadku, tzn. dla alokacji przy zastosowaniu tablicy wskaźników, aby alokować tablicę dwuwymiarową alokuje się jej poszczególne wiersze stosując elementy tablicy wskaźników, int i,n=5,m=5; for (i=0;i<n;i++) ptab[i]=(int*) calloc(m, sizeof(int)); // każdy ze wskaźników ptab[i] wskazuje na pierwszy // element i-tego wiersza tablicy Język ANSI C – dynamiczna alokacja pamięci Alokacja dynamiczna tablic dwuwymiarowych w języku C W drugim przypadku stosuje się wskaźnik do tablicy jednowymiarowej, ( wskaźnik do wiersza tablicy) i alokuje się obszar pamięci odpowiadający rozmiarem rozmiarowi tablicy i następnie przekształca się obszar na tablicę dwuwymiarową stosując rzutowanie na wskaźnik do tablicy ( w języku C nie jest konieczne jawne rzutowanie) int n=2,m=2; int (*pa)[m];// pa jest wskaźnikiem do tablicy //jednowymiarowej liczb typu int pa=(int (*)[m])calloc(n*m,sizeof(int)); // lub pa=calloc(n*m,sizeof(int)); Język ANSI C – dynamiczna alokacja pamięci Przykład. Alokacja dynamiczna tablicy dwuwymiarowej typu int ( wersja z tablicą wskaźników). (cz. 1) #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int n=2,m=2; int *pa[n]; //pa jest tablicą wskaźnikow do int int i,j; for (i=0;i<n;i++) pa[i]=(int *)calloc(m,sizeof(int)); Język ANSI C – dynamiczna alokacja pamięci Przykład. Alokacja dynamiczna tablicy dwuwymiarowej typu int ( wersja tablicy wskaźników). (cz. 2) // wczytywanie tablicy for (i=0;i<n;i++) for (j=0;j<m;j++) { printf("\n Podaj element[%d][%d]=",i,j); scanf("%d",pa[i]+j);// I-sza forma //scanf("%d",pa[i]++); // II-ga forma } //for (i=0;i<n;i++)- konieczne dla II formy // pa[i]=pa[i]-m; cofanie wskaźnika Język ANSI C – dynamiczna alokacja pamięci Przykład. Alokacja dynamiczna tablicy dwuwymiarowej typu int (wersja tablicy wskaźników)(cz. 3). // Drukowanie tablicy for (i=0;i<n;i++) { for (j=0;j<m;j++) printf(" %d ",*(pa[i]+j)); //printf(" %d ",*pa[i]++); II forma printf("\n"); } system("PAUSE"); //for (i=0;i<n;i++)- konieczne dla II formy // pa[i]=pa[i]-m; cofanie wskaźnika for (i=0;i<n;i++)free pa[i]; } Język ANSI C – dynamiczna alokacja pamięci Przykład. Alokacja dynamiczna tablicy dwuwymiarowej typu int ( wersja indeksowa). (cz. 1) #include <stdio.h> #include <stdlib.h> int n=2; m=2; int (*pa)[m]; // pa jest wskaznikiem //do tablicy jednowymiarowej liczb typu int int i,j; pa=(int (*)[m])calloc(n*m,sizeof(int)); for (i=0;i<n;i++) for (j=0;j<m;j++) { printf("\n Podaj element[%d][%d]=",i,j); scanf("%d",&pa[i][j]); } Język ANSI C – dynamiczna alokacja pamięci Przykład. Alokacja dynamiczna tablicy dwuwymiarowej typu int ( wersja indeksowa). (cz. 2) // Wydruk tablicy for (i=0;i<n;i++) { for (j=0;j<m;j++) printf(" %d ",pa[i][j]); printf("\n"); } free(pa); system("pause"); }