niedziela, 12 czerwca 2016

C - Przydzielanie pamięci

Ten post chciałbym poświęcić opisowi takich funkcji jak calloc, malloc, free oraz realloc, które są zdefiniowane w stdlib.h.

calloc - pozwala na przydzielenie tablicy elementów o podanym rozmiarze. Zwracany jest wskaźnik do przydzielonej pamięci lub wartość NULL jeśli operacja się nie powiedzie. Dodatkowo przydzielona pamięć jest ustawiana na wartość 0.  Funkcja wygląda następująco:

void *calloc(size_t nitems, size_t size)

Pierwsza wartość oznacza liczbę elementów jakie mają zostać przydzielone. Drugi parametr oznacza wielkość tych elementów.

free - pozwala na cofnięcie przydzielenia pamięci jakie zostało wykonane przez funckję calloc, malloc albo realloc. Deklaracja wygląda następująco:

void free(void *ptr)

Parametr umieszczony wewnątrz funkcji jest wskaźnikiem na blok pamięci który został wcześniej wykorzystany przez inne funkcje. Funkcja nie zwraca żadnej wartości. Jeśli podana zostanie wartość NULL wtedy funkcja nie wykona żadnych operacji.

malloc - pozwala na przydzielenie pamięci. Jej deklaracja wygląda następująco:

void *malloc(size_t size)

Parametrem jest wielkość bloku pamięci w bajtach. Zwracana jest wskaźnik do pamięci jeśli operacja się powiedzie, lub NULL jeśli nie uda się przydzielić pamięci.

realloc - pozwala na ponowne przydzielenie pamięci dla danych, które były już wstawiane poprzez użycie funkcji malloc albo calloc.

void *realloc(void *ptr, size_t size)

Pierwsza wartość stanowi wskaźnik do pamięci. Jeśli będzie to wartość NULL wtedy nowy blok pamięci zostanie przydzielony oraz wskaźnik do tej wartości zostanie zwrócony przez funkcję. Drugi parametr natomiast stanowi nowy rozmiar bloku w bajtach. Jeśli parametr wynosi 0 i wskaźnik wskazuje na istniejący blok pamięci wtedy następuje przeniesienie elementów i zwrócenie NULL przez funkcję.

Poniżej przedstawiam krótki program obrazujący sposoby wykorzystania każdej z wymienionych funkcji.

W pierwszym kroku z klawiatury podawana jest ilość elementów oraz ich wartość. Następnie funkcją calloc jest im przydzielana pamięć o rozmiarze int.  Po czym dane są wprowadzane do kolejnych miejsc. Dalej zostanie wyświetlone wprowadzone wartości wraz z adresem, po czym pamięć będzie zwolniona i ponowne przedstawienie znajdujących się tam wartości. Jak widać na rysunku 1 są to już dane przypadkowe. Kolejnym etapem będzie funkcja malloc i realloc. Pierwsza przydzieli pamięć i wartość, druga natomiast nie zmieniając poprzednio wprowadzonej informacji zwiększy rozmiar i dopisze nowy fragment.

  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. int main()
  5. {
  6.    int element = 0;
  7.    int ilosc = 0;
  8.    int *wskaznik;
  9.    char *wskaznik2;
  10.    //CALLOC
  11.    //Wprowadzenie liczby elementow oraz ich wartosc
  12.    printf("Ilosc elementow jakie beda przydzielone:");
  13.    scanf("%d",&ilosc);
  14.    wskaznik = (int*)calloc(ilosc, sizeof(int));
  15.    printf("Podaj %d elementy:\n",ilosc);
  16.    for( element=0 ; element < ilosc ; element++ )
  17.    {
  18.       scanf("%d",&wskaznik[element]);
  19.    }
  20.    printf("Podane wartosci: ");
  21.    for( element=0 ; element < ilosc ; element++ )
  22.    {
  23.       printf("%d,  ", wskaznik[element]);
  24.       printf("%u; ", &wskaznik[element]);
  25.    }
  26.    printf("\n");
  27.    free( wskaznik );
  28.    printf("Elementy po zwolnieniu pamieci: ");
  29.    for( element=0 ; element < ilosc ; element++ )
  30.    {
  31.       printf("%d, ",wskaznik[element]);
  32.       printf("%u; ", &wskaznik[element]);
  33.    }
  34.    printf("\n");
  35.    //MALLOC
  36.    wskaznik2 =  (char*)malloc(sizeof(char));
  37.    strcpy(wskaznik2, "DZIALA");
  38.    printf("wartosc: %s, adress: %u \n", wskaznik2, wskaznik2);
  39.    //REALLOC
  40.    wskaznik2 = (char*)realloc(wskaznik2, 5*sizeof(char));
  41.    strcat(wskaznik2, " - NOWA WARTOSC");
  42.    printf("wartosc: %s, adress: %u \n", wskaznik2, wskaznik2);
  43.    free(wskaznik2);
  44.    printf("wartosc: %s, adress: %u \n", wskaznik2, wskaznik2);
  45.    return(0);
  46. }

Poniżej znajduje się efekt działania programu:

Rys. 1. Wynik działania programu