Jason. Cała informatyka w jednym miejscu!

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. Teraźniejszy temat to będzie tablica o zmiennym rozmiarze (ang. "variable length array"), czyli w skrócie "VLA" w języku C, to 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" W JĘZYKU C?

Tablica o zmiennym rozmiarze umożliwia nam definiowanie 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ą). Wadą tego jest to, że nie możemy zadeklarować tablicy i za jednym zamachem wprowadzić wartości. Dla zobrazowania o co mi chodzi. Taki zapis:

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

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

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

PRZYKŁAD KODU ŹRÓDŁOWEGO

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", "VLA" w języku C jest szczególnie użyteczne 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 "VLA" w języku C 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 tablica o zmiennym rozmiarze. "VLA" w języku C otrzymuje rozmiary wymiarów na podstawie użytych stałych liczb całkowitych. Ponieważ tutaj 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.


Jesteście przygotowani na na kolejny artykuł o tablicach?

PODOBNE ARTYKUŁY