Wskaźniki Przemysław Gawroński D-10, p. 234 Wykład 2 8 marca 2019 (Wykład 2) Wskaźniki 8 marca 2019 1 / 17
Outline 1 Wskaźniki 2 Tablice a wskaźniki 3 Dynamiczna alokacja pamięci (Wykład 2) Wskaźniki 8 marca 2019 2 / 17
Wskaźniki Korzyści płynące ze wskaźników: (Wykład 2) Wskaźniki 8 marca 2019 3 / 17
Wskaźniki Korzyści płynące ze wskaźników: wskaźniki umożliwiają funkcjom modyfikowanie swoich argumentów, (Wykład 2) Wskaźniki 8 marca 2019 3 / 17
Wskaźniki Korzyści płynące ze wskaźników: wskaźniki umożliwiają funkcjom modyfikowanie swoich argumentów, wskaźniki są podstawą dynamicznej alokacji pamięci, (Wykład 2) Wskaźniki 8 marca 2019 3 / 17
Wskaźniki Korzyści płynące ze wskaźników: wskaźniki umożliwiają funkcjom modyfikowanie swoich argumentów, wskaźniki są podstawą dynamicznej alokacji pamięci, wskaźniki umożliwiają realizację dynamicznych struktur danych: listy, drzewa, itp, (Wykład 2) Wskaźniki 8 marca 2019 3 / 17
Wskaźniki Korzyści płynące ze wskaźników: wskaźniki umożliwiają funkcjom modyfikowanie swoich argumentów, wskaźniki są podstawą dynamicznej alokacji pamięci, wskaźniki umożliwiają realizację dynamicznych struktur danych: listy, drzewa, itp, wskaźniki pozwalają poprawić efektywność działania wielu procedur. (Wykład 2) Wskaźniki 8 marca 2019 3 / 17
Wskaźniki Wskaźnik to zmienna przechowująca adres innej zmiennej. (Wykład 2) Wskaźniki 8 marca 2019 4 / 17
Wskaźniki Wskaźnik to zmienna przechowująca adres innej zmiennej. Adres zmiennej to informacja o jej fizycznej lokalizacji w pamięci programu. (Wykład 2) Wskaźniki 8 marca 2019 4 / 17
Wskaźniki Wskaźnik to zmienna przechowująca adres innej zmiennej. Adres zmiennej to informacja o jej fizycznej lokalizacji w pamięci programu. Ogólna postać deklaracji wskaźnika: typ *nazwa; (Wykład 2) Wskaźniki 8 marca 2019 4 / 17
Wskaźniki Wskaźnik to zmienna przechowująca adres innej zmiennej. Adres zmiennej to informacja o jej fizycznej lokalizacji w pamięci programu. Ogólna postać deklaracji wskaźnika: typ *nazwa; Operator & zwraca adres w pamięci następującego po nim operandu. (Wykład 2) Wskaźniki 8 marca 2019 4 / 17
Wskaźniki Wskaźnik to zmienna przechowująca adres innej zmiennej. Adres zmiennej to informacja o jej fizycznej lokalizacji w pamięci programu. Ogólna postać deklaracji wskaźnika: typ *nazwa; Operator & zwraca adres w pamięci następującego po nim operandu. Operator * zwraca wartość zmiennej, znajdującej się pod adresem następującyn po operandzie. (Wykład 2) Wskaźniki 8 marca 2019 4 / 17
Wskaźniki Wskaźnik to zmienna przechowująca adres innej zmiennej. Adres zmiennej to informacja o jej fizycznej lokalizacji w pamięci programu. Ogólna postać deklaracji wskaźnika: typ *nazwa; Operator & zwraca adres w pamięci następującego po nim operandu. Operator * zwraca wartość zmiennej, znajdującej się pod adresem następującyn po operandzie. Na wskaźnikach można wykonywać tylko dwie operacje arytmetyczne: dodawanie i odejmowanie. (Wykład 2) Wskaźniki 8 marca 2019 4 / 17
Wskaźniki Wskaźnik to zmienna przechowująca adres innej zmiennej. Adres zmiennej to informacja o jej fizycznej lokalizacji w pamięci programu. Ogólna postać deklaracji wskaźnika: typ *nazwa; Operator & zwraca adres w pamięci następującego po nim operandu. Operator * zwraca wartość zmiennej, znajdującej się pod adresem następującyn po operandzie. Na wskaźnikach można wykonywać tylko dwie operacje arytmetyczne: dodawanie i odejmowanie. Operacje wskaźnikowe wykonywane są z uwzględnieniem typu podstawowego wskaźnika. (Wykład 2) Wskaźniki 8 marca 2019 4 / 17
Tablice i adresy - arytmetyka wskaźników # define SIZE 8 int itab [ SIZE ], * pit = itab ; // int * pit =& itab [0]; double dtab [ SIZE ], * pdt = dtab ; printf (" %18 s %15 s\n", " int ", " double "); for ( int i = 0; i < SIZE ; i ++) // gnu11 printf (" wsk + %d %10 p %10 p\n",i,pit +i,pdt +i); (Wykład 2) Wskaźniki 8 marca 2019 5 / 17
Tablice i adresy - arytmetyka wskaźników # define SIZE 8 int itab [ SIZE ], * pit = itab ; // int * pit =& itab [0]; double dtab [ SIZE ], * pdt = dtab ; printf (" %18 s %15 s\n", " int ", " double "); for ( int i = 0; i < SIZE ; i ++) // gnu11 printf (" wsk + %d %10 p %10 p\n",i,pit +i,pdt +i); int double wsk + 0 : 0x7fff36430c60 0x7fff36430c10 wsk + 1 : 0x7fff36430c64 0x7fff36430c18 wsk + 2 : 0x7fff36430c68 0x7fff36430c20 wsk + 3 : 0x7fff36430c6c 0x7fff36430c28 wsk + 4 : 0x7fff36430c70 0x7fff36430c30 wsk + 5 : 0x7fff36430c74 0x7fff36430c38 wsk + 6 : 0x7fff36430c78 0x7fff36430c40 wsk + 7 : 0x7fff36430c7c 0x7fff36430c48 (Wykład 2) Wskaźniki 8 marca 2019 5 / 17
Czym są tablice? W języku C dla tablic przewidziano tylko 2 operacje: (Wykład 2) Wskaźniki 8 marca 2019 6 / 17
Czym są tablice? W języku C dla tablic przewidziano tylko 2 operacje: określenie rozmiaru tablicy, (Wykład 2) Wskaźniki 8 marca 2019 6 / 17
Czym są tablice? W języku C dla tablic przewidziano tylko 2 operacje: określenie rozmiaru tablicy, uzyskanie adresu pierwszego elementu tablicy (o indeksie zerowym). (Wykład 2) Wskaźniki 8 marca 2019 6 / 17
Czym są tablice? W języku C dla tablic przewidziano tylko 2 operacje: określenie rozmiaru tablicy, uzyskanie adresu pierwszego elementu tablicy (o indeksie zerowym). Wszystkie pozostałe operacje są w istocie realizowane na wskaźnikach, nawet jeśli zapis sugeruje co innego, np. tab[i]. (Wykład 2) Wskaźniki 8 marca 2019 6 / 17
Czym są tablice? W języku C dla tablic przewidziano tylko 2 operacje: określenie rozmiaru tablicy, uzyskanie adresu pierwszego elementu tablicy (o indeksie zerowym). Wszystkie pozostałe operacje są w istocie realizowane na wskaźnikach, nawet jeśli zapis sugeruje co innego, np. tab[i]. W języku C nazwa tab odnosi się do adresu elementu tablicy tab[] o indeksie zero w każdym kontekście, z wyjątkiem jednego, kiedy to występuje jako argument operatora sizeof. (Wykład 2) Wskaźniki 8 marca 2019 6 / 17
Czym są tablice? W języku C dla tablic przewidziano tylko 2 operacje: określenie rozmiaru tablicy, uzyskanie adresu pierwszego elementu tablicy (o indeksie zerowym). Wszystkie pozostałe operacje są w istocie realizowane na wskaźnikach, nawet jeśli zapis sugeruje co innego, np. tab[i]. W języku C nazwa tab odnosi się do adresu elementu tablicy tab[] o indeksie zero w każdym kontekście, z wyjątkiem jednego, kiedy to występuje jako argument operatora sizeof. Zapis sizeof tab - reprezentuje rozmiar całej tablicy, a nie rozmiar wskaźnika jednego z jej elementów. (Wykład 2) Wskaźniki 8 marca 2019 6 / 17
Czym są tablice? int tab[100]; *tab = 18 - przypisujemy wartość elementowi o indeksie 0. (Wykład 2) Wskaźniki 8 marca 2019 7 / 17
Czym są tablice? int tab[100]; *tab = 18 - przypisujemy wartość elementowi o indeksie 0. *(tab + 5) = 18 - przypisujemy wartość elementowi o indeksie 5. (Wykład 2) Wskaźniki 8 marca 2019 7 / 17
Czym są tablice? int tab[100]; *tab = 18 - przypisujemy wartość elementowi o indeksie 0. *(tab + 5) = 18 - przypisujemy wartość elementowi o indeksie 5. *(tab + 5) = 18 - działa tak samo jak *(5 + tab) = 18. (Wykład 2) Wskaźniki 8 marca 2019 7 / 17
Czym są tablice? int tab[100]; *tab = 18 - przypisujemy wartość elementowi o indeksie 0. *(tab + 5) = 18 - przypisujemy wartość elementowi o indeksie 5. *(tab + 5) = 18 - działa tak samo jak *(5 + tab) = 18. tab[5] = 18 - przypisujemy wartość elementowi o indeksie 5. (Wykład 2) Wskaźniki 8 marca 2019 7 / 17
Czym są tablice? int tab[100]; *tab = 18 - przypisujemy wartość elementowi o indeksie 0. *(tab + 5) = 18 - przypisujemy wartość elementowi o indeksie 5. *(tab + 5) = 18 - działa tak samo jak *(5 + tab) = 18. tab[5] = 18 - przypisujemy wartość elementowi o indeksie 5. tab[5] = 18 - działa tak samo jak 5[tab]=18. (Wykład 2) Wskaźniki 8 marca 2019 7 / 17
Czym są tablice? int tab[100]; *tab = 18 - przypisujemy wartość elementowi o indeksie 0. *(tab + 5) = 18 - przypisujemy wartość elementowi o indeksie 5. *(tab + 5) = 18 - działa tak samo jak *(5 + tab) = 18. tab[5] = 18 - przypisujemy wartość elementowi o indeksie 5. tab[5] = 18 - działa tak samo jak 5[tab]=18. Notacja 5[tab] = 18 - działa, ale nie powinna być stosowana. (Wykład 2) Wskaźniki 8 marca 2019 7 / 17
Czym są tablice? int tab[100]; *tab = 18 - przypisujemy wartość elementowi o indeksie 0. *(tab + 5) = 18 - przypisujemy wartość elementowi o indeksie 5. *(tab + 5) = 18 - działa tak samo jak *(5 + tab) = 18. tab[5] = 18 - przypisujemy wartość elementowi o indeksie 5. tab[5] = 18 - działa tak samo jak 5[tab]=18. Notacja 5[tab] = 18 - działa, ale nie powinna być stosowana. Wyrażenie X[Y] jest równoważne wyrażeniu *(X+Y). (Wykład 2) Wskaźniki 8 marca 2019 7 / 17
Czym są tablice? int tab[100]; *tab = 18 - przypisujemy wartość elementowi o indeksie 0. *(tab + 5) = 18 - przypisujemy wartość elementowi o indeksie 5. *(tab + 5) = 18 - działa tak samo jak *(5 + tab) = 18. tab[5] = 18 - przypisujemy wartość elementowi o indeksie 5. tab[5] = 18 - działa tak samo jak 5[tab]=18. Notacja 5[tab] = 18 - działa, ale nie powinna być stosowana. Wyrażenie X[Y] jest równoważne wyrażeniu *(X+Y). Wyrażenie &X[Y] jest równoważne wyrażeniu X+Y. (Wykład 2) Wskaźniki 8 marca 2019 7 / 17
Tablice i wskaźniki char tab[] i char *p to to samo tylko w przypadku parametrów formalnych funkcji. (Wykład 2) Wskaźniki 8 marca 2019 8 / 17
Tablice i wskaźniki char tab[] i char *p to to samo tylko w przypadku parametrów formalnych funkcji. Deklaracja char tab[6] przydziela miejsce na 6 znaków i wiąże ten obszar z nazwą tab. (Wykład 2) Wskaźniki 8 marca 2019 8 / 17
Tablice i wskaźniki char tab[] i char *p to to samo tylko w przypadku parametrów formalnych funkcji. Deklaracja char tab[6] przydziela miejsce na 6 znaków i wiąże ten obszar z nazwą tab. Deklaracja char *p przydziela miejsce na 1 wskaźnik. Wskaźnik może wskazywać: (Wykład 2) Wskaźniki 8 marca 2019 8 / 17
Tablice i wskaźniki char tab[] i char *p to to samo tylko w przypadku parametrów formalnych funkcji. Deklaracja char tab[6] przydziela miejsce na 6 znaków i wiąże ten obszar z nazwą tab. Deklaracja char *p przydziela miejsce na 1 wskaźnik. Wskaźnik może wskazywać: na pojedynczą zmienną typu char, (Wykład 2) Wskaźniki 8 marca 2019 8 / 17
Tablice i wskaźniki char tab[] i char *p to to samo tylko w przypadku parametrów formalnych funkcji. Deklaracja char tab[6] przydziela miejsce na 6 znaków i wiąże ten obszar z nazwą tab. Deklaracja char *p przydziela miejsce na 1 wskaźnik. Wskaźnik może wskazywać: na pojedynczą zmienną typu char, na dowolny indeks w tablicy typu char, (Wykład 2) Wskaźniki 8 marca 2019 8 / 17
Tablice i wskaźniki char tab[] i char *p to to samo tylko w przypadku parametrów formalnych funkcji. Deklaracja char tab[6] przydziela miejsce na 6 znaków i wiąże ten obszar z nazwą tab. Deklaracja char *p przydziela miejsce na 1 wskaźnik. Wskaźnik może wskazywać: na pojedynczą zmienną typu char, na dowolny indeks w tablicy typu char, nigdzie - wskaźnik pusty. (Wykład 2) Wskaźniki 8 marca 2019 8 / 17
Tablice i wskaźniki Przykład: char tab[]= hello ; char *p = world ; (Wykład 2) Wskaźniki 8 marca 2019 9 / 17
Tablice i wskaźniki Przykład: char tab[]= hello ; char *p = world ; tab: 'h' 'e' 'l' 'l' 'o' '\0' (Wykład 2) Wskaźniki 8 marca 2019 9 / 17
Tablice i wskaźniki Przykład: char tab[]= hello ; char *p = world ; tab: 'h' 'e' 'l' 'l' 'o' '\0' p: 'w' 'o' 'r' 'l' 'd' '\0' (Wykład 2) Wskaźniki 8 marca 2019 9 / 17
Tablice i wskaźniki Przykład: char tab[]= hello ; char *p = world ; tab: 'h' 'e' 'l' 'l' 'o' '\0' p: 'w' 'o' 'r' 'l' 'd' '\0' Jak przetłumaczyć x[3]??? (Wykład 2) Wskaźniki 8 marca 2019 9 / 17
Tablice i wskaźniki Przykład: char tab[]= hello ; char *p = world ; tab: 'h' 'e' 'l' 'l' 'o' '\0' p: 'w' 'o' 'r' 'l' 'd' '\0' Jak przetłumaczyć x[3]??? tab[3] - weź adres tablicy tab dodaj do niego 3 i pobierz znak, (Wykład 2) Wskaźniki 8 marca 2019 9 / 17
Tablice i wskaźniki Przykład: char tab[]= hello ; char *p = world ; tab: 'h' 'e' 'l' 'l' 'o' '\0' p: 'w' 'o' 'r' 'l' 'd' '\0' Jak przetłumaczyć x[3]??? tab[3] - weź adres tablicy tab dodaj do niego 3 i pobierz znak, p[3] - weź adres wskaźnika p, pobierz jego wartość, dodaj do niej 3 i pobierz znak. Gdzie znajduje się x[3]??? (Wykład 2) Wskaźniki 8 marca 2019 9 / 17
Tablice i wskaźniki Przykład: char tab[]= hello ; char *p = world ; tab: 'h' 'e' 'l' 'l' 'o' '\0' p: 'w' 'o' 'r' 'l' 'd' '\0' Jak przetłumaczyć x[3]??? tab[3] - weź adres tablicy tab dodaj do niego 3 i pobierz znak, p[3] - weź adres wskaźnika p, pobierz jego wartość, dodaj do niej 3 i pobierz znak. Gdzie znajduje się x[3]??? tab[3] - znak odległy o 3 miejsca od początku obiektu o nazwie tab, (Wykład 2) Wskaźniki 8 marca 2019 9 / 17
Tablice i wskaźniki Przykład: char tab[]= hello ; char *p = world ; tab: 'h' 'e' 'l' 'l' 'o' '\0' p: 'w' 'o' 'r' 'l' 'd' '\0' Jak przetłumaczyć x[3]??? tab[3] - weź adres tablicy tab dodaj do niego 3 i pobierz znak, p[3] - weź adres wskaźnika p, pobierz jego wartość, dodaj do niej 3 i pobierz znak. Gdzie znajduje się x[3]??? tab[3] - znak odległy o 3 miejsca od początku obiektu o nazwie tab, p[3] - znak odległy o 3 miejsca od obiektu wskazywanego przez p. (Wykład 2) Wskaźniki 8 marca 2019 9 / 17
Przekazywanie tablic do funkcji W języku C nie można (i nie trzeba) przekazać do funkcji całej tablicy. (Wykład 2) Wskaźniki 8 marca 2019 10 / 17
Przekazywanie tablic do funkcji W języku C nie można (i nie trzeba) przekazać do funkcji całej tablicy. Do funkcji można przekazać tylko i wyłącznie adres do pierwszego elementu tablicy, podając nazwę tablicy bez indeksu. (Wykład 2) Wskaźniki 8 marca 2019 10 / 17
Przekazywanie tablic do funkcji W języku C nie można (i nie trzeba) przekazać do funkcji całej tablicy. Do funkcji można przekazać tylko i wyłącznie adres do pierwszego elementu tablicy, podając nazwę tablicy bez indeksu. Przykład: int main ( void ){ int tab [10]; func ( tab ); return 0; } (Wykład 2) Wskaźniki 8 marca 2019 10 / 17
Przekazywanie tablic do funkcji W języku C nie można (i nie trzeba) przekazać do funkcji całej tablicy. Do funkcji można przekazać tylko i wyłącznie adres do pierwszego elementu tablicy, podając nazwę tablicy bez indeksu. Przykład: int main ( void ){ int tab [10]; func ( tab ); return 0; } 3 sposoby deklaracji funkcji func(): void func ( int *x); void func ( int x [10]) ; void func ( int x []) ; (Wykład 2) Wskaźniki 8 marca 2019 10 / 17
Przekazywanie tablic do funkcji W języku C nie można (i nie trzeba) przekazać do funkcji całej tablicy. Do funkcji można przekazać tylko i wyłącznie adres do pierwszego elementu tablicy, podając nazwę tablicy bez indeksu. Przykład: int main ( void ){ int tab [10]; func ( tab ); return 0; } 3 sposoby deklaracji funkcji func(): void func ( int *x); void func ( int x [10]) ; void func ( int x []) ; Wewnątrz funkcji func() wyrażenie sizeof x zwraca rozmiar wskaźnika, a nie tablicy. (Wykład 2) Wskaźniki 8 marca 2019 10 / 17
Przekazywanie tablic do funkcji W języku C nie można (i nie trzeba) przekazać do funkcji całej tablicy. Do funkcji można przekazać tylko i wyłącznie adres do pierwszego elementu tablicy, podając nazwę tablicy bez indeksu. Przykład: int main ( void ){ int tab [10]; func ( tab ); return 0; } Wewnątrz funkcji func() wyrażenie sizeof x zwraca rozmiar wskaźnika, a nie tablicy. Rozmiar tablicy musimy przekazać jawnie: void func ( int *x, int roz ); void func ( int x [10], int roz ); void func ( int x[], int roz ); (Wykład 2) Wskaźniki 8 marca 2019 11 / 17
Modyfikatory dostępu dla tablic (C99) Standard C99 pozwala na użycie słowa kluczowego static wewnątrz nawiasów w deklaracji tablicy, jeśli występuje jako parametr funkcji. (Wykład 2) Wskaźniki 8 marca 2019 12 / 17
Modyfikatory dostępu dla tablic (C99) Standard C99 pozwala na użycie słowa kluczowego static wewnątrz nawiasów w deklaracji tablicy, jeśli występuje jako parametr funkcji. Przykład: int fun ( char str [ static 80]) {... } Słowo kluczowe static informuje kompilator, że tablica wskazywana przez parametr str będzie zawierała co najmniej określoną (80) liczbę elementów. (Wykład 2) Wskaźniki 8 marca 2019 12 / 17
Przekazywanie tablic do funkcji - przykład # define SIZE 10 int sump ( int * start, int * end ) { int total = 0; while ( start < end ) total += * start ++; } return total ; (Wykład 2) Wskaźniki 8 marca 2019 13 / 17
Przekazywanie tablic do funkcji - przykład # define SIZE 10 int sump ( int * start, int * end ) { int total = 0; while ( start < end ) total += * start ++; } return total ; int tab [ SIZE ] = {20,10,5,39,4,16,19,26,31,20}; int sum = sump ( tab, tab + SIZE ); (Wykład 2) Wskaźniki 8 marca 2019 13 / 17
Dynamiczna alokacja pamięci - stdlib.h Dynamiczna alokacja pamięci to sposób, w jaki działający program uzyskuje dodatkową pamięć, której ilości nie można określić przed jego uruchomieniem. (Wykład 2) Wskaźniki 8 marca 2019 14 / 17
Dynamiczna alokacja pamięci - stdlib.h Dynamiczna alokacja pamięci to sposób, w jaki działający program uzyskuje dodatkową pamięć, której ilości nie można określić przed jego uruchomieniem. Dynamiczna alokacja pamięci umożliwia tworzenie dynamicznych(abstrakcyjnych) struktur danych. (Wykład 2) Wskaźniki 8 marca 2019 14 / 17
Dynamiczna alokacja pamięci - stdlib.h Dynamiczna alokacja pamięci to sposób, w jaki działający program uzyskuje dodatkową pamięć, której ilości nie można określić przed jego uruchomieniem. Dynamiczna alokacja pamięci umożliwia tworzenie dynamicznych(abstrakcyjnych) struktur danych. Funkcje dynamicznej alokacji pamięci przydzielają pamięć ze sterty. (Wykład 2) Wskaźniki 8 marca 2019 14 / 17
Dynamiczna alokacja pamięci - stdlib.h Dynamiczna alokacja pamięci to sposób, w jaki działający program uzyskuje dodatkową pamięć, której ilości nie można określić przed jego uruchomieniem. Dynamiczna alokacja pamięci umożliwia tworzenie dynamicznych(abstrakcyjnych) struktur danych. Funkcje dynamicznej alokacji pamięci przydzielają pamięć ze sterty. Rozmiar sterty z reguły jest dość duży, jednak ograniczony i pamięć ze sterty może się wyczerpać. (Wykład 2) Wskaźniki 8 marca 2019 14 / 17
Dynamiczna alokacja pamięci - stdlib.h void *malloc(size t size); - przydziela blok pamięci o rozmiarze size, nie inicjalizując go. Funkcja zwraca adres bloku, a w przypadku niepowodzenia NULL. (Wykład 2) Wskaźniki 8 marca 2019 15 / 17
Dynamiczna alokacja pamięci - stdlib.h void *malloc(size t size); - przydziela blok pamięci o rozmiarze size, nie inicjalizując go. Funkcja zwraca adres bloku, a w przypadku niepowodzenia NULL. void *calloc(size t n, size t size); - przydziela miejsce dla tablicy n elementów każdy o rozmiarze size, wszystkie bity w rezerwowanym obszarze otrzymują wartość 0. Funkcja zwraca adres bloku, a w przypadku niepowodzenia NULL. (Wykład 2) Wskaźniki 8 marca 2019 15 / 17
Dynamiczna alokacja pamięci - stdlib.h void *malloc(size t size); - przydziela blok pamięci o rozmiarze size, nie inicjalizując go. Funkcja zwraca adres bloku, a w przypadku niepowodzenia NULL. void *calloc(size t n, size t size); - przydziela miejsce dla tablicy n elementów każdy o rozmiarze size, wszystkie bity w rezerwowanym obszarze otrzymują wartość 0. Funkcja zwraca adres bloku, a w przypadku niepowodzenia NULL. void free(void *ptr); - zwalnia obszar pamięci wskazywany przez ptr, ptr - powinien być wartością zwróconą wcześniej przez malloc(), calloc() lub realloc(). (Wykład 2) Wskaźniki 8 marca 2019 15 / 17
Dynamiczna alokacja pamięci - stdlib.h void *malloc(size t size); - przydziela blok pamięci o rozmiarze size, nie inicjalizując go. Funkcja zwraca adres bloku, a w przypadku niepowodzenia NULL. void *calloc(size t n, size t size); - przydziela miejsce dla tablicy n elementów każdy o rozmiarze size, wszystkie bity w rezerwowanym obszarze otrzymują wartość 0. Funkcja zwraca adres bloku, a w przypadku niepowodzenia NULL. void free(void *ptr); - zwalnia obszar pamięci wskazywany przez ptr, ptr - powinien być wartością zwróconą wcześniej przez malloc(), calloc() lub realloc(). free(null) nie powoduje żadnej akcji, nie trzeba sprawdzać czy adres jest różny od NULL przed wywołaniem free. (Wykład 2) Wskaźniki 8 marca 2019 15 / 17
stdlib.h - malloc int *p = malloc (50 * sizeof ( int )); if (!p){ printf (" Brak pamieci \n"); // wyjscie awaryjne // return ; lub return x; // lub exit ( -1); }... free (p); (Wykład 2) Wskaźniki 8 marca 2019 16 / 17
stdlib.h - malloc int *p = malloc (50 * sizeof ( int )); if (!p){ printf (" Brak pamieci \n"); // wyjscie awaryjne // return ; lub return x; // lub exit ( -1); }... free (p); W języku C nie rzutujemy adresu zwracanego przez malloc(). (Wykład 2) Wskaźniki 8 marca 2019 16 / 17
stdlib.h - malloc int *p = malloc (50 * sizeof ( int )); if (!p){ printf (" Brak pamieci \n"); // wyjscie awaryjne // return ; lub return x; // lub exit ( -1); }... free (p); W języku C nie rzutujemy adresu zwracanego przez malloc(). Rzutowanie konieczne było w latach 70 i 80 kiedy malloc() zwracał char*. (Wykład 2) Wskaźniki 8 marca 2019 16 / 17
stdlib.h - malloc int *p = malloc (50 * sizeof ( int )); if (!p){ printf (" Brak pamieci \n"); // wyjscie awaryjne // return ; lub return x; // lub exit ( -1); }... free (p); W języku C nie rzutujemy adresu zwracanego przez malloc(). Rzutowanie konieczne było w latach 70 i 80 kiedy malloc() zwracał char*. Dla dowolnego typu: typ *p = malloc (n * sizeof ( typ )); (Wykład 2) Wskaźniki 8 marca 2019 16 / 17
stdlib.h - realloc void *realloc(void *ptr, size t size); - zmienia rozmiar bloku pamięci wskazywanego przez ptr na size. (Wykład 2) Wskaźniki 8 marca 2019 17 / 17
stdlib.h - realloc void *realloc(void *ptr, size t size); - zmienia rozmiar bloku pamięci wskazywanego przez ptr na size. Dotychczasowa zawartość bloku pamięci pozostaje niezmieniona, ale może zostać skrócona, jeśli nowy rozmiar jest mniejszy niż poprzedni. (Wykład 2) Wskaźniki 8 marca 2019 17 / 17
stdlib.h - realloc void *realloc(void *ptr, size t size); - zmienia rozmiar bloku pamięci wskazywanego przez ptr na size. Dotychczasowa zawartość bloku pamięci pozostaje niezmieniona, ale może zostać skrócona, jeśli nowy rozmiar jest mniejszy niż poprzedni. Jeżeli przydzielenie miejsca było niemożliwe, to funkcja zwraca NULL i pozostawia pierwotny blok bez zmian. (Wykład 2) Wskaźniki 8 marca 2019 17 / 17
stdlib.h - realloc void *realloc(void *ptr, size t size); - zmienia rozmiar bloku pamięci wskazywanego przez ptr na size. Dotychczasowa zawartość bloku pamięci pozostaje niezmieniona, ale może zostać skrócona, jeśli nowy rozmiar jest mniejszy niż poprzedni. Jeżeli przydzielenie miejsca było niemożliwe, to funkcja zwraca NULL i pozostawia pierwotny blok bez zmian. Przykład. int * tab = malloc ( SIZE * sizeof ( int ));... tab = realloc (tab,( SIZE -A)* sizeof ( int ));... tab = realloc (tab,( SIZE +A)* sizeof ( int ));... free ( tab ); (Wykład 2) Wskaźniki 8 marca 2019 17 / 17
stdlib.h - realloc void *realloc(void *ptr, size t size); - zmienia rozmiar bloku pamięci wskazywanego przez ptr na size. Dotychczasowa zawartość bloku pamięci pozostaje niezmieniona, ale może zostać skrócona, jeśli nowy rozmiar jest mniejszy niż poprzedni. Jeżeli przydzielenie miejsca było niemożliwe, to funkcja zwraca NULL i pozostawia pierwotny blok bez zmian. Przykład. int * tab = malloc ( SIZE * sizeof ( int ));... tab = realloc (tab,( SIZE -A)* sizeof ( int ));... tab = realloc (tab,( SIZE +A)* sizeof ( int ));... free ( tab ); realloc(null, size) jest równoważne malloc(size). (Wykład 2) Wskaźniki 8 marca 2019 17 / 17
stdlib.h - realloc void *realloc(void *ptr, size t size); - zmienia rozmiar bloku pamięci wskazywanego przez ptr na size. Dotychczasowa zawartość bloku pamięci pozostaje niezmieniona, ale może zostać skrócona, jeśli nowy rozmiar jest mniejszy niż poprzedni. Jeżeli przydzielenie miejsca było niemożliwe, to funkcja zwraca NULL i pozostawia pierwotny blok bez zmian. Przykład. int * tab = malloc ( SIZE * sizeof ( int ));... tab = realloc (tab,( SIZE -A)* sizeof ( int ));... tab = realloc (tab,( SIZE +A)* sizeof ( int ));... free ( tab ); realloc(null, size) jest równoważne malloc(size). realloc(ptr, 0) jest równoważne free(ptr). (Wykład 2) Wskaźniki 8 marca 2019 17 / 17