C/malloc: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Derbeth (dyskusja | edycje)
formatowanie, przecinki
Mina86 (dyskusja | edycje)
połączony opis z calloc, realloc i free
Linia 1:
===Deklaracja===
 
: #include <[[C/Biblioteka standardowa/Indeks tematyczny#stdlib.h|stdlib.h]]>
: <tt>void *malloc( size_t size );</tt>
void *calloc(size_t nmeb, size_t size);
: <tt> void *malloc( size_t size );</tt>
void free(void *ptr);
void *realloc(void *ptr, size_t size);
 
===Argumenty===
;nmeb :liczba elementów, dla których ma być przydzielona pamięć
; size : rozmiar (w bajtach) pamięci do zarezerwowania bądź rozmiar pojedynczego elementu
;ptr :wskaźnik zwrócony przez poprzednie wywołanie jednej z funkcji lub NULL
 
===Plik nagłówkowyOpis===
Funkcja calloc przydziela pamięć dla <tt>nmeb</tt> elementów o rozmiarze <tt>size</tt> każdy i zeruje przydzieloną pamięć.
 
Funkcja malloc przydziela pamięć o wielkości <tt>size</tt> bajtów.
: [[C/Biblioteka standardowa/Indeks tematyczny#stdlib.h|stdlib.h]]
 
Funkcja free zwalnia blok pamięci wskazywany przez <tt>ptr</tt> wcześniej przydzielony przez jedną z funkcji malloc, calloc lub realloc. Jeżeli <tt>ptr</tt> ma wartość NULL funkcja nie robi nic.
 
Funkcja realloc zmienia rozmiar przydzielonego wcześniej bloku pamięci wskazywanego przez <tt>ptr</tt> do <tt>size</tt> bajtów. Pierwsze <tt>n</tt> bajtów bloku nie ulegnie zmianie gdzie <tt>n</tt> jest minimum z rozmiaru starego bloku i <tt>size</tt>. Jeżeli <tt>ptr</tt> jest równy zero (tj. NULL), funkcja zachowuje się tak samo jako malloc.
===Argumenty===
; size : rozmiar (w bajtach) pamięci do zarezerwowania
 
===Wartość zwracana===
Jeżeli przydzielanie pamięci się powiodło, funkcje calloc, malloc i realloc zwracają wskaźnik do nowo przydzielonego bloku pamięci. W przypadku funkcji realloc może to być wartość inna niż <tt>ptr</tt>.
 
:Jeśli jako <tt>size</tt>, <tt>nmeb</tt> podano 0zero, zwracany jest albo wskaźnik NULL albo prawidłowy wskaźnik, który można podać do funkcji free (zauważmy, że [[Programowanie:C:Wskaźniki#Na co wskazuje NULL?|NULL]] jest też prawidłowym argumentem free).
===Opis===
 
: Jeśli działanie funkcji nie powiedzie się, zwracany jest NULL i odpowiedni kod błędu jest wpisywany do zmiennej [[C/errno|errno]]. Dzieje się tak zazwyczaj, gdy nie ma wystarczająco dużo miejsca w pamięci.
:Funkcja pobiera jako argument rozmiar pamięci, jaką ma zarezerwować na stercie, i zwraca wskaźnik do zaalokowanego obszaru.
 
 
===Wartość zwracana===
:Wskaźnik do zarezerwowanego bloku pamięci.
:Jeśli jako <tt>size</tt> podano 0, zwracany jest albo wskaźnik NULL albo prawidłowy wskaźnik, który można podać do funkcji free (zauważmy, że [[Programowanie:C:Wskaźniki#Na co wskazuje NULL?|NULL]] jest też prawidłowym argumentem free).
: Jeśli działanie funkcji nie powiedzie się, zwracany jest NULL i odpowiedni kod błędu jest wpisywany do zmiennej [[C/errno|errno]]. Dzieje się tak zazwyczaj, gdy nie ma wystarczająco dużo miejsca w pamięci.
 
===Przykład===
#include <stdlibstdio.h>
#include <stdlib.h>
int main(void) {
{
size_t size, num int= rozmiar0;
float *tablicatab, tmp;
/* Przydzielenie początkowego bloku pamięci */
rozmiar = 3;
size = 64;
tablicatab = malloc(rozmiarsize * sizeof *tablicatab);
if (!tablica) {
if (!tab) {
return 1;
}perror("malloc");
return tablica[0] = 0.1EXIT_FAILURE;
free(tablica);
return 0;
}
/* Odczyt liczb */
while (scanf("%f", &tmp)==1) {
/* Jeżeli zapełniono całą tablicę, trzeba ją zwiększyć */
if (num==size) {
float *ptr = realloc(tab, (size *= 2) * sizeof *ptr);
if (!tablicaptr) {
free(tablicatab);
perror("realloc");
return 1EXIT_FAILURE;
return 0;}
rozmiar tab = 3ptr;
}
tab[num++] = tmp;
}
/* Wypisanie w odwrotnej kolejnosci */
while (num) {
printf("%f\n", tab[--num]);
{}
/* Zwolnienie pamieci i zakonczenie programu */
free(tab);
return EXIT_SUCCESS;
}
 
===Uwagi===
Użycie rzutowania przy wywołaniach funkcji malloc, [[C/realloc|realloc]] oraz [[C/calloc|calloc]] w języku C jest zbędne i szkodliwe. W przypadku braku deklaracji tych funkcji (np. gdy programista zapomni dodać plik nagłówkowy [[C/Biblioteka standardowa/Indeks tematyczny#stdlib.h|stdlib.h]]) kompilator przyjmuje domyślną deklaracje, w której funkcja zwraca int. Przy braku rzutowania spowoduje to błąd kompilacji (z powodu niemożności skonwertowania liczby na wskaźnik) co pozwoli na szybkie wychwycenie błędu w programie. Rzutowanie powoduje, że kompilator zostaje zmuszony do przeprowadzenia konwersji typów i nie wyświetla żadnych błędów. W przypadku języka [[C++]] rzutowanie jest konieczne.
 
Zastosowanie operatora sizeof z wyrażeniem (np. <tt>sizeof *tablica</tt>), a nie typem (np. <tt>sizeof float</tt>) ułatwia późniejszą modyfikację programów. Gdyby w pewnym momencie programista zdecydował się zmienić tablicę z tablicy floatów na tablice double'i, musiałby wyszukiwać wszystkie wywołania funkcji malloc, [[C/realloc|realloc]] i [[C/calloc|calloc]], co nie jest konieczne przy użyciu operatora sizeof z wyrażeniem.
Użycie rzutowania przy wywołaniach funkcji malloc, [[C/realloc|realloc]] oraz [[C/calloc|calloc]] w języku C jest zbędne i szkodliwe. W przypadku braku deklaracji tych funkcji (np. gdy programista zapomni dodać plik nagłówkowy [[C/Biblioteka standardowa/Indeks tematyczny#stdlib.h|stdlib.h]]) kompilator przyjmuje domyślną deklaracje, w której funkcja zwraca int. Przy braku rzutowania spowoduje to błąd kompilacji (z powodu niemożności skonwertowania liczby na wskaźnik) co pozwoli na szybkie wychwycenie błędu w programie. Rzutowanie powoduje, że kompilator zostaje zmuszony do przeprowadzenia konwersji typów i nie wyświetla żadnych błędów. W przypadku języka [[C++]] rzutowanie jest konieczne.
 
Zastosowanie operatora sizeof z wyrażeniem (np. <tt>sizeof *tablica</tt>), a nie typem (np. <tt>sizeof float</tt>) ułatwia późniejszą modyfikację programów. Gdyby w pewnym momencie programista zdecydował się zmienić tablicę z tablicy floatów na tablice double'i, musiałby wyszukiwać wszystkie wywołania funkcji malloc, [[C/realloc|realloc]] i [[C/calloc|calloc]], co nie jest konieczne przy użyciu operatora sizeof z wyrażeniem.
 
Warto zauważyć, że w przypadku standardowych konfiguracji systemu GNU/Linux funkcje przydzielające pamięć nigdy nie zawodzą i nie zwracają wartości NULL (dla wartości parametru <tt>size</tt> większego od zera).
Linia 53 ⟶ 80:
 
=== Zobacz też ===
: [[C/calloc|calloc]] (alokowanie i zerowanie pamięci)
: [[C/realloc|realloc]] (przealokowanie pamięci)
: [[C/free|free]] (zwolnienie pamięci)
: [[C/Wskaźniki]] (dokładne omówienie zastosowania)