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");
}