Mamy sobotę więc czas wrócić do niedokończonego epizodu na temat tablic w języku C! Zakończmy te dwa artykuły o których była mowa, żebym miał to już z głowy. Teraźniejszy temat to będzie tablica o zmiennym rozmiarze (ang. "variable length array" w skrócie "VLA"), kolejny dodatek standardu C99 z 1999 roku wprowadzony przez organizację ISO. Patrząc na termin to trochę może być dziwne rozumowanie czym konkretnie jest "zmienny rozmiar". Czyżby język C oferował jakąś prototypową rewolucję w postaci tablicy dynamicznej? A może chodzi o możliwość wprowadzania do funkcji tablic o różnych rozmiarach, nie tylko sztywno ustawionych w kodzie? Rozwiejmy te wątpliwości raz na zawsze.

CO NAM OFERUJE TABLICA O ZMIENNYM ROZMIARZE?

VLA umożliwia nam deklarowanie tablic podając rozmiary wymiarów w postaci zmiennych, zatem wbrew wstępnemu wnioskowaniu, to NIE JEST żadna tablica dynamiczna, że sobie żonglujemy rozmiarami jak chcemy (takie rzeczy to tylko przy manualnym zarządzaniu pamięcią, któregoś razu pewnie o tym napiszę). Wadą tego jest to, że nie możemy przydzielić pamięci i za jednym zamachem wprowadzić wartości. Dla zobrazowania o co mi chodzi:

int numbers[ROWS][COLUMNS] = {{...}, {...}, ...};

jest niedopuszczalne! Natomiast przy tradycyjnej tablicy już to jest dozwolone:

int numbers[2][4] = {{5, 7, 34, -100}, {-97, 56, 8, 42}};

KOD ŹRÓDŁOWY Z VLA

Dobrze, wytknęliśmy wadę. A zalety? Oprócz możliwości uzależnienia rozmiaru tablicy od innych obiektów danych typu "liczba całkowita", tablica o zmiennym rozmiarze jest szczególnie użyteczna przy wprowadzeniu funkcji dokonujących operacji na tablicach. Tradycyjnie, musielibyśmy definiować każdą osobną funkcję dla rozmiaru N drugiego wymiaru w taki sposób:

#define COLUMNS 3

int printNumbers(int array[][COLUMNS], int rows)
{
	for (int r = 0; r < rows; ++r)
	{
		for (int c = 0; c < COLUMNS; ++c)
		{
			printf("array[%d][%d] = %d\n", r, c, array[r][c]);
		}
	}
}

Wywołania przy których drugi wymiar jest zawsze równy 3 wypalą, ale w razie innego rozmiaru byłby już spory kłopot. W języku C, sztywno ustawiane rozmiary wymiarów tablic MUSZĄ być jasno określone w nagłówku funkcji z wyjątkiem pierwszego wymiaru najbardziej "wysuniętego na lewo" od nazwy. A to dlatego, że język automatycznie traktuje podaną tablicę jako wskaźnik i żeby móc przemieszczać się po argumentach "wskaźnikowo", kompilator musi wiedzieć jakiego rozmiaru są wszystkie wymiary. Wyjątkiem jest ten pierwszy wymiar z racji tego, że zgodnie z notacją wskaźnikową, inkrementowanie samego adresu tablicy powoduje "przesunięcie się" o jeden wymiar do przodu (w tym przypadku o jeden cały rząd). Tak wygląda tablica o zmiennym rozmiarze w akcji:

#include <stdio.h>

void assignNumbers(int rows, int columns, int array[rows][columns]);
void printSum(int rows, int columns, int array[rows][columns]);

int main(void)
{
	int numbersA[3][2] =
	{
		{67, 105},
		{100, -97},
		{88, -915}
	};
	
	const int ROWS = 4, COLUMNS = 6;
	int numbersB[ROWS][COLUMNS];			// tablica o zmiennym rozmiarze (VLA)
	
	assignNumbers(ROWS, COLUMNS, numbersB);
	printSum(3, 2, numbersA);
	printSum(ROWS, COLUMNS, numbersB);
	getchar();
	
	return 0;
}

void assignNumbers(int rows, int columns, int array[rows][columns])
{
	for (int r = 0; r < rows; ++r)
	{
		for (int c = 0; c < columns; ++c)
		{
			array[r][c] = columns*r + c + 1;
		}
	}
}

void printSum(int rows, int columns, int array[rows][columns])
{
	for (int r = 0; r < rows; ++r)
	{
		for (int c = 0; c < columns; ++c)
		{
			printf("array[%d][%d] = %d\n", r, c, array[r][c]);
		}
	}
	
	putchar('\n');
}

To już nieco większy kod. Po ustaleniu prototypów funkcji, w "main" tworzymy dwie tablice dwuwymiarowe. Jedna za pomocą tradycyjnego zapisu ANSI C, a druga to VLA. Tablica o zmiennym rozmiarze otrzymuje rozmiary wymiarów na podstawie użytych stałych liczb całkowitych. Ponieważ przy VLA niemożliwe jest inicjalizowanie wartości, wywołujemy funkcję przypisującą numerki do argumentów, a następnie sprawdzamy wszystkie wartości obu tablic przy użyciu "printSum". Takie są wnioski końcowe.


Bądźcie przygotowani na kolejny artykuł o tablicach w dniu dzisiejszym już za kilka godzin!

PODOBNE ARTYKUŁY