# 12 Лекция Полная версия [TOC] ## Про память ### Массив массивов Массив массивов может выделяться 3мя разными способами: --- 1) ![](https://i.imgur.com/3Z8Um1x.jpg) --- 2) ![](https://i.imgur.com/AY6m7Ot.jpg) --- 3) ![](https://i.imgur.com/0GOp0eH.jpg) --- ### Двумерный массив Двумерный массив выделяется так: ```c= int g[5][5]; //В секции данных, фикс размер int main(void) { int h = 8, w = 10; //Могут быть введены пользователем int a[5][5]; //На стеке, мало памяти и фикс размер int *m = malloc(sizeof(int) * h * w); //h - высота, w - ширина g[2][3]; a[2][3]; m[2*w + 3]; //неудобный доступ к элементам free(m); return 0; } ``` ### VLA **Есть ещё один способ** сделать двумерный массив ***ТОЛЬКО В СИ***, выделить на куче, и с нормальным доступом: (трудный для понимания): ```c int main(void) { int h = 8, w = 10; //Могут быть введены пользователем //h - высота, w - ширина int (*m)[w] = malloc(sizeof(int) * h * w); //VLA указатель m[2][3]; free(m); return 0; } ``` В этом примере мы использовали понятие массива с неконстантной длинной, VLA - variable length array Не все компиляторы это умеют. Дело в том, что добавили это только в стандарт C99, но убрали из обязательной части стандарта в оптиональную в C11, те компиляторы, которые не поддерживают стандарт C99, не умеют в VLA (например microsoft), даже в VLA указатели (данный пример) VLA массивом называют локальный или глобальный массив с неконстантным размером. Многие утверждаю, что это зло - **так и есть**, потому что такие массивы 1) Не имеют ограничей по длинне (может забить стек) 2) При попадании такого в цикл, компилятор обязан хитро уметь в реальном времени освобождать и выделять место на стеке прям посреди функции (обычно делается при входе в функцию) VLA называю злом из-за того, что *"Тупые хомячки"* используют его для создания динамического массива на стеке (VLA массив), вместо создания хитрого типа переменного размера (VLA указатель). На самом деле идея очень хорошая, но только в качестве VLA указателей. В 23 стандарте хотят вернуть часть VLA (указатели) в обязательную часть стандарта --- #### Как выглядит VLA массив (зло) **Как НЕ надо писать** ```c int w = 5; const int w_const = 5; int g[5]; //НЕ VLA array - Так НАДО int g_vla[w]; //VLA array int g_also_vla[w_const]; //VLA array int main (void) { int w_in_main = 5; const int w_in_main_const = 5; int a[5]; //НЕ VLA array - Так НАДО int a_vla[w]; //VLA array int a_also_vla[w_const]; //VLA array } ``` --- #### Передача VLA указателя в функцию Нужно сначала передать в функцию размер массива: ```c void f(int h, int w, int a[h][w]) // первая размерность всегда превратиться в указатель { } //или void f(int w, int a[][w]) // первая размерность всегда превратиться в указатель { } ```