---
# System prepended metadata

title: 11 Лекция Полная версия

---

# 11 Лекция Полная версия

[TOC]

## Про память

### Секции

Три секции:
1) секция кода - код
2) секция данных - глобальные переменные (`static` локальные тоже)
3) секция данных на чтение - глобальные константы
---
4) Stack - локальные переменные
5) Free RAM (Heap) - куда происходит выделение памяти (обычно называют кучей)

И всё это лежит в оперативной памяти.

![](https://i.imgur.com/pYWBQoS.png)

[ПОДРОБНЕЕ](https://stackoverflow.com/questions/53942282/where-will-the-initialized-data-segment-values-are-stored-before-run-time)

[ПОДРОБНЕЕ 2](https://www.geeksforgeeks.org/memory-layout-of-c-program)

### Выделение памяти

Для выделения памяти нам и нужны указатели:
```c=
#include <stdio.h>
#include <stdlib.h>

int main (void)
{
    int w = 1000;
    //int a[1000]; - создание обычного статического массива
    // так не надо при больших количествах информации
    // тк локальные масивы храняться на стеке (+- 2мб на программу)

    int *a = malloc(sizeof(int) * w); //создание массива с выделением памяти

    if(a == NULL) // проверять рекомендуется при выделении большого размера
    {
        printf("Memory was not allocated!\n");
        return 1;
    }
        
    
    a[999]; // доступ такой же
     
    free(a);    // освободить память
    // функции free можно отдавать NULL
}
```

`malloc`, возвращает `void *`, принимает количество байт которые нужно *попросить* выделить систему

Религиозный вопрос про проверку. Проверять рекомендуется при выделении большого размера в памяти, тк при выделении маленького - есть огромная веротность что уже всё остальное тоже сломалось.

В си **НЕ** нужно кастовать указатель из `void *` к `int *` (*в ++ нужно, по религиозным причинам*)

Освобождать память нужно точно **таким же способом** (семейство функций), каким и выделили (на будущее). Так проиходит из-за того, что у разных функций выделения - разные вспомогательные данные, из-за этого ещё если мы попросим выделить 0 байт, то место в оперативной памяти такая штука займет больше 0.

> В системе существует много разных способов (функций) выделить память, для разных нужд:
> * просто выделение
> * выделить очень много
> * чтобы была возможность отдать другому процессу
> * и т.д. 

#### Доступ

Доступ к выделенной памяти такой же как и у одномерных массивов, тк синтаксис `[]` это ни что иное, как разьменование и перемещение указателя. Обычные одномерные массивы почти тоже самое, что указатель, за исключением того, что:
1) указатель не знает рамер массива
2) массив нельзя переопределить (указатель можно заставить указывать на другое место в памяти)
3) нельзя создать указатель на массив, он будет тем же самым указателем

### Передача массива в функцию

```c

int sum(int x[3]) //или int x[] -> (int *x) автоматически будет преобразованно
{
    return x[0] + x[1] + x[2];
    //return (*(x + 0)) + (*(x + 1)) + (*(x + 2));
}


int main(void)
{
    int a[3] = {1, 2}; //1, 2, 0
    return sum(a);
}
```

Массивы в аргументах функций **никогда** не бывают массивами, они автоматически преобразуются до указателя. (альтернативная запись указателя - `int x[]`)

=> массивы никогда не **копируются** в функцию, любое изменение которые мы сдлаем с массивом внутри функции будет видно там, где этот массив создавали.

### Разница массива массивов и двумерного массива

1) **Массив массивов** (`int **m;`)
   * хранится массив указатей на строки, а затем разбросанно по памяти строки
   * строки могут быть разного размера
   * два обращения в память (медленнее)
   * строки могут поменены местами за O(1) (очень быстро)
   ![](https://i.imgur.com/mrTCgJo.jpg)
2) **Двумерный массив** (`int m[h][w];`)
   * храниться в памяти подряд
   * строки единого размера 
   * одно обращение в память (быстрее)
   * строки можно поменять местами минимум за O(w) (довольно медленно)
   ![](https://i.imgur.com/p5d8DSN.jpg)
   
Разницу нужно понимать, тк обращение к этим двум обьектам выглядит идентично - `m[i][j]`

> В двумерном массиве нужный указатель вычисляется с помощью умножение, фактически,  двумерный массив - это одномерный массив

### Массив массивов

Массив массивов может выделяться 3мя разными способами:

--- 

1) ![](https://i.imgur.com/3Z8Um1x.jpg)

---

2) ![](https://i.imgur.com/AY6m7Ot.jpg)

---

3) ![](https://i.imgur.com/0GOp0eH.jpg)

---