# 12 Лекция Полная версия
[TOC]
## Про память
### Массив массивов
Массив массивов может выделяться 3мя разными способами:
---
1) 
---
2) 
---
3) 
---
### Двумерный массив
Двумерный массив выделяется так:
```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]) // первая размерность всегда превратиться в указатель
{
}
```