Powiększanie za pomocą realloc
Zmieni Pan/Pani rozmiar dynamicznej tablicy.
Powiększanie za pomocą realloc to bezpłatna lekcja C Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C Academy zawiera 4 lekcji w sumie.
Gdy jeden malloc nie wystarcza
Czasami przydzielają Państwo tablicę, wypełniają ją, a następnie odkrywają, że potrzebne jest więcej miejsca. Nie można po prostu zapisywać poza jej końcem.
realloc pozwala zmienić rozmiar istniejącego bloku na stercie, zachowując znajdujące się w nim dane.
Sygnatura realloc
realloc(ptr, new_bytes) przyjmuje stary wskaźnik oraz nowy całkowity rozmiar w bajtach.
Zwraca wskaźnik do bloku o nowym rozmiarze. Początkowa część danych jest zachowywana do mniejszego z dwóch rozmiarów: starego i nowego.
int *bigger = realloc(a, new_n * sizeof(*a));Blok może zostać przeniesiony
realloc może powiększyć blok w miejscu albo przydzielić nowy blok, skopiować dane i zwolnić stary.
W obu przypadkach stary wskaźnik może stać się nieprawidłowy. Od tej pory należy używać zwróconego wskaźnika.
a = realloc(a, new_n * sizeof(*a));
/* the old value of a may no longer be valid */Pułapka przypisania do tej samej zmiennej
Zapis a = realloc(a, ...) wygląda schludnie, ale jest niebezpieczny: jeśli realloc zwróci NULL, zmienna a zostanie nadpisana i utracą Państwo oryginalny wskaźnik, powodując wyciek starego bloku.
Należy zamiast tego użyć zmiennej tymczasowej.
int *tmp = realloc(a, new_n * sizeof(*a));
if (tmp == NULL) { /* a is still valid */ return 1; }
a = tmp;Bezpieczne powiększanie tablicy
Ten program przydziela miejsce na 3 liczby całkowite, a następnie powiększa blok do 6 za pomocą realloc, zachowując trzy pierwsze wartości.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *a = malloc(3 * sizeof(*a));
if (!a) return 1;
for (int i = 0; i < 3; i++) a[i] = i + 1;
int *tmp = realloc(a, 6 * sizeof(*a));
if (!tmp) { free(a); return 1; }
a = tmp;
for (int i = 3; i < 6; i++) a[i] = i + 1;
for (int i = 0; i < 6; i++) printf("%d\n", a[i]);
free(a);
return 0;
}Nowe bajty są niezainicjalizowane
Po powiększeniu bloku dodatkowe miejsce na jego końcu zawiera przypadkowe dane, tak jak świeżo przydzielona pamięć za pomocą malloc.
realloc zachowuje stare dane, ale nie zeruje nowego obszaru. Przed odczytem należy go zainicjalizować.
a = realloc(a, 6 * sizeof(*a));
for (int i = 3; i < 6; i++) a[i] = 0; /* clear new slots */Strategia podwajania
Wywoływanie realloc dla każdego pojedynczego elementu jest powolne. Klasycznym rozwiązaniem jest podwajanie pojemności za każdym razem, gdy zabraknie miejsca.
Dzięki temu liczba operacji realloc pozostaje niewielka podczas powiększania tablicy, zapewniając dobrą średnią wydajność.
if (count == cap) {
cap = cap ? cap * 2 : 4;
int *tmp = realloc(a, cap * sizeof(*a));
if (!tmp) { free(a); return 1; }
a = tmp;
}Budowanie tablicy przez dopisywanie
Ten program zaczyna od pustej tablicy i dopisuje liczby, w razie potrzeby podwajając jej pojemność.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *a = NULL;
size_t count = 0, cap = 0;
for (int v = 1; v <= 5; v++) {
if (count == cap) {
cap = cap ? cap * 2 : 2;
int *tmp = realloc(a, cap * sizeof(*a));
if (!tmp) { free(a); return 1; }
a = tmp;
}
a[count++] = v;
}
for (size_t i = 0; i < count; i++) printf("%d\n", a[i]);
free(a);
return 0;
}realloc(NULL, n) działa jak malloc
Jeśli jako wskaźnik zostanie przekazane NULL, realloc działa dokładnie tak samo jak malloc.
Dlatego rozpoczęcie od a = NULL działa w pętli podwajającej: pierwsze wywołanie realloc przydziela początkowy blok.
int *a = NULL;
a = realloc(a, 4 * sizeof(*a)); /* same as malloc(4 * sizeof(*a)) */Zmniejszanie bloku
realloc może również zmniejszyć blok. Dane do nowego rozmiaru zostają zachowane, a reszta jest odrzucana.
Zmniejszenie może zwolnić część pamięci, choć implementacje mogą zachować większy blok.
int *tmp = realloc(a, 2 * sizeof(*a)); /* down from more */
if (tmp) a = tmp;Unikanie przepełnienia w obliczeniach
Gdy pojemność staje się duża, wyrażenie cap * sizeof(*a) może spowodować przepełnienie typu size_t i zawinąć się do bardzo małej wartości.
W przypadku ogromnych tablic należy zabezpieczyć mnożenie przed przepełnieniem lub użyć reallocarray w systemach, które je udostępniają.
if (cap > SIZE_MAX / sizeof(*a)) { /* overflow */ return 1; }
int *tmp = realloc(a, cap * sizeof(*a));Szybkie sprawdzenie
Sprawdź, jak dobrze rozumiesz działanie realloc.
Podsumowanie
realloc zmienia rozmiar bloku na stercie i może go przenieść, dlatego zawsze należy używać zwróconego wskaźnika.
Przypisz wynik do zmiennej tymczasowej, aby błąd nie spowodował utraty oryginalnego bloku. Dla szybkości zwiększaj pojemność dwukrotnie, inicjalizuj nowe elementy i pamiętaj, że realloc(NULL, n) jest równoważne malloc. Następnie zamkną Państwo tę logikę w wielokrotnego użytku typie wektora.
Często zadawane pytania
Czy lekcja „Powiększanie za pomocą realloc” jest bezpłatna?
Tak — pełny tekst „Powiększanie za pomocą realloc” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C Academy, przejdź na CoddyKit PRO. Kurs C Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Powiększanie za pomocą realloc”?
Zmieni Pan/Pani rozmiar dynamicznej tablicy. Ćwiczysz C Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć C Academy?
Nie wymagamy żadnego doświadczenia. C Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Powiększanie za pomocą realloc”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji C Academy?
Tak. Każda lekcja C Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Alokowanie tablicy
- Powiększanie za pomocą realloc
- Wielokrotnego użytku typ wektora
- Zwalnianie pamięci i unikanie wycieków