Ukazatele, dynamická alokace paměti, pole
Download
Report
Transcript Ukazatele, dynamická alokace paměti, pole
Verze 2009.01
10 Ukazatele a pole
A1PRG - Programování – Seminář
Ing. Michal Heczko [email protected]
Agenda
Ukazatele
Nulový
ukazatel
Obecný ukazatel
Aritmetika ukazatelů
Dynamické přidělování paměti
Ukazatel
Při dosavadní práci s proměnnými použity tzv.
statické proměnné.
Ukazatel (Pointer) je proměnná, která představuje
adresu v paměti, na které je uložena skutečná
hodnota.
Ukazatel
Ukazatel je proměnná
Neobsahuje hodnotu, ale pouze paměťovou adresu
Zajímá nás hodnota ležící na adrese, kterou
definuje
Každý ukazatel ukazuje na určitý datový typ
(ukazatel na celé číslo, …)
Ukazatel
Pojmy:
Adresa
Obsah
ukazatele
ukazatele / Hodnota ukazatele
Hodnota
na níž ukazatel ukazuje
Operátory
Operátor reference
Operátor:
&
Význam: Vrací adresu proměnné
Operátor dereference
Operátor:
*
Význam: Vrací obsah zadané adresy
Příklad 1
int i;
int *p_i1;
int *p_i2;
Příkaz
Obsah na adrese
10 (&i)
20 (&p_i1)
30 (&p_i2)
i = 1;
1
?
?
p_i1 = &i;
1
10
?
*p_i1 = 2;
2
10
?
i = *p_i1 + 1;
3
10
?
p_i2 = &p_i1;
3
10
20
Příklad 2
#include "stdafx.h"
#include <conio.h>
int _tmain(int argc, _TCHAR* argv[])
{
int i, j, *p_i;
scanf("%d %d",&i,&j);
p_i = (i > j) ? &i : &j;
printf("Vetsi je %d na adrese %p",*p_i,p_i);
getch();
return 0;
}
Nulový ukazatel
Symbolická konstanta NULL
Lze přiřadit libovolnému ukazateli bez ohledu na
datový typ
Označení, že ukazatel „neukazuje nikam“
Nulový ukazatel
Příklad:
Otevření
neexistujícího souboru (v případě, že soubor
neexistuje, vrací funkce hodnotu NULL):
FILE *f;
f = fopen(″soubor.txt″,″r″);
if (f == NULL)
printf(″Soubor neexistuje″);
Obecný ukazatel
Generický ukazatel na typ void
Po správném přetypování může ukazovat na data
libovolného typu
Obecný ukazatel
void *p;
int a = 5;
double b = 2.8e36;
p = &a;
* (int *) p = 7;
p = &b;
* (double *) p = 12.83;
Příklad
Funkce pro záměnu dvou proměnných
void zamen(int *p_i, int *p_j)
{
int pom;
pom = *p_i;
*p_i = *p_j;
*p_j = pom;
}
Aritmetika ukazatelů
Součet (a rozdíl) ukazatele a celého čísla
Rozdíl ukazatelů
Porovnání ukazatelů
Aritmetika ukazatelů
Součet (a rozdíl) ukazatele a celého čísla:
Přičtením
celého čísla k ukazateli vzniká ukazatel nový.
Nový ukazatel bude ukazovat o N adres dále.
Pokud ukazatel bude ukazovat na prvek struktury,
která v paměti zabírá 10 B, přičtením 1 bude nový
ukazatel ukazovat o 10 B dále.
Př.
int *p_i;
p_i = p_i + 1;
Aritmetika ukazatelů
Rozdíl ukazatelů:
Vrací
počet údajů, které leží mezi prvním a druhým
ukazatelem.
Rozdíl ukazatelů má smysl například u polí
Porovnání ukazatelů (==):
Vrací
hodnotu 1, pokud ukazatele ukazují na stejné
místo v paměti.
U polí možno použít i další relační operátory.
Dynamické přidělování paměti
Umožňuje uživateli řídit přidělování paměti
Paměť je přidělována z tzv. hromady (heap)
Problém: přidělování paměti tak, aby nedošlo ke
kolizi s ostatními daty.
Přidělení paměti pomocí funkce malloc().
Uvolnění paměti pomocí funkce free().
Dynamické přidělování paměti
Funkce malloc()
Rezervace
paměti
Jediný parametr typu unsigned int – počet bytů
Návratová hodnota: ukazatel na typ void – obsahuje
adresu prvního prvku v paměti
Je
vhodné přetypovat na potřebný datový typ
Není-li v paměti dostatek místa pro přidělení žádaného
úseku, vrací hodnotu NULL
Dynamické přidělování paměti
Funkce free()
Uvolnění
paměti
Parametrem je ukazatel na typ void
Dynamické přidělování paměti
Příklad:
int *p_i;
if ((p_i = (int *)malloc(sizeof(int))) == NULL)
{
printf("Nedostatek pameti!");
}
else
{
printf("Zadejte celociselnou hodnotu: ");
scanf("%d", p_i);
printf("Zadana hodnota: %d",*p_i);
free(p_i);
}
Dynamické přidělování paměti
Funkce calloc()
Alokace
paměti pro určitý počet prvků dané velikosti
Parametry:
Počet
prvků
Velikost jednoho prvku - počet bytů
Návratová
hodnota: ukazatel na typ void – obsahuje
adresu prvního prvku v paměti
Dynamické přidělování paměti
Funkce calloc()
Srovnání
s funkcí malloc()
malloc ( n * size );
calloc ( n , size );
Pole
„Struktura“ složená se stejných prvků
Jednotlivé prvky indexujeme od 0
Př.:
int x[10];
x[0] = 10;
for (int i = 0; i < 10; i++)
{
x[i] = i;
}
Statické pole
Nevýhoda: nutno zadat konstantní rozměr pole
Př.:
int x[10];
x[0] = 10;
for (int i = 0; i < 10; i++)
{
x[i] = i;
}
Dynamické pole
Možnost zadat rozměr pole na základě proměnné.
Definice pomocí malloc() (popř. calloc())
Př.:
int *x;
x = (int *) malloc(10*sizeof(int));
for (int i = 0; i < 10; i++)
{
*(x+i) = i;
}
Statické / dynamické pole
Akce
Statické pole
Dynamické pole
Definice
int x[5];
int *x;
x = malloc(5*sizeof(int))
Naplnění n-tého
prvku pole
hodnotou
x[n] = 5;
*(x + n) = 5;
Adresa n-tého
prvku (např. u
příkazu scanf)
scanf("%d",&x[n]);
scanf("%d",(x+n));
Uvolnění paměti
free(x)
Vícerozměrná pole
Jazyk C umožňuje definici pole s vyšší dimenzí než
1.
Dvourozměrné pole:
int x[10][10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++)
x[i][j] = 0;
}
}
{
Vícerozměrná pole
Trojrozměrné pole:
int x[10][10][10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++)
x[i][j][k] = 0;
}
}
}
{
Vícerozměrná pole
Statické pole
int pole[2][2];
Po
celou dobu má rozměr 2x2
Polostatické pole
int *pole[2];
pole[0] = (int *)malloc(4*sizeof(int));
pole[1] = (int *)malloc(8*sizeof(int));
Počet
prvků
řádků neměnná, každý řádek má různý počet
Vícerozměrná pole
Dynamické pole
int **pole;
pole = (int **) malloc(2*sizeof(int *));
pole[0] = (int *)malloc(4*sizeof(int));
pole[1] = (int *)malloc(8*sizeof(int));
Zcela
flexibilní
Vícerozměrná pole
Transformace dvourozměrného pole na
jednorozměrné
int *pole;
int r = 3;
int s = 2;
pole = (int *)malloc(r*s*sizeof(int));
//přístup k pole[2][1]
*(pole + (2*s + 1)) = 5;
Inicializace pole
Hodnoty uvádíme ve složených závorkách
int x[3] = {2, 3, 5};
int y[] = {1, 2};
Pokud v inicializaci uvedeme méně prvků, zbylé jsou
inicializovány na 0
int x[3] = {2, 3};
Na druhou stranu není možné uvést prvků více:
int y[2] = {1, 2, 4};
Inicializace pole
Vícerozměrné pole
int x[][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
A1PRG-s
10. Ukazatele a pole
Děkuji za pozornost
Ing. Michal Heczko
[email protected]
218/U3
Prezentace k dispozici na http://vyuka.fai.utb.cz