Tablice o zmiennej długości (VLA — Variable Length Arrays) pojawiły się w standardzie C99, przedtem wszystkie rozmiary tablic musiały być znane na etapie kompilacji. Pozwalają na deklarację tablic, których rozmiar jest określany przez zmienną znaną dopiero w czasie wykonania.
Nieprawidłowe użycie VLA prowadzi do nieprzechwyconych błędów alokacji pamięci (np. zbyt duży rozmiar tablicy prowadzi do przepełnienia stosu), niemożności przekazywania VLA między różnymi kompilatorami (nie wszystkie je obsługują) oraz ograniczonej zgodności z wcześniejszymi standardami C i C++. Ponadto debugowanie jest utrudnione, ponieważ pamięć jest alokowana na stosie, a nie w stercie, co nie zawsze jest oczekiwane.
Używając VLA, należy pamiętać, że żyją one na stosie i nie mogą być zmiennymi globalnymi ani statycznymi. Lepiej preferować dynamiczne tablice za pomocą malloc, jeśli potrzebna jest elastyczność i gwarantowana kompatybilność z C++. Dla kompatybilności warto ograniczyć się do tablic statycznych lub standardów C90, jeśli wsparcie dla VLA nie jest gwarantowane.
Przykład kodu:
#include <stdio.h> void process(size_t n) { int arr[n]; // VLA for(size_t i = 0; i < n; i++) arr[i] = i; for(size_t i = 0; i < n; i++) printf("%d ", arr[i]); } int main() { process(5); return 0; }
Kluczowe cechy:
Czy można zadeklarować statyczną tablicę o zmiennej długości jako static int arr[n]; wewnątrz funkcji?
Nie, zmienne statyczne muszą mieć określony rozmiar na etapie kompilacji. Dlatego static int arr[n]; z zmiennym rozmiarem spowoduje błąd kompilacji.
Czy VLA zostaną automatycznie zwolnione po wyjściu z funkcji?
Tak, VLA są umieszczane na stosie i ich pamięć jest automatycznie zwalniana po wyjściu z bloku/funkcji, tak jak w przypadku zwykłych zmiennych lokalnych.
Czy bezpiecznie jest alokować VLA o bardzo dużym rozmiarze?
Nie, rozmiar stosu jest ograniczony (na przykład 1 MB lub 8 MB). Próba alokacji dużego VLA zakończy się błędem wykonania (przepełnienie stosu).
Pisano kod wieloplatformowy z VLA, który nie kompilował się na starszych lub ściśle skonfigurowanych kompilatorach.
Zalety:
Wady:
Używano VLA tylko do lokalnych zadań i tam, gdzie gwarantowany był mały rozmiar, dla dużych tablic — malloc/free.
Zalety:
Wady: