0Pricing
C Academy · Lekcja

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

  1. Alokowanie tablicy
  2. Powiększanie za pomocą realloc
  3. Wielokrotnego użytku typ wektora
  4. Zwalnianie pamięci i unikanie wycieków
← Powrót do C Academy