пятница, 1 апреля 2016 г.

Указатели: стек.

    Раньше я думал, что люди делятся на два типа: те, кто понимает указатели и те, кто их не понимает. А оказалось, люди делятся на два других типа: те, кто может объяснить указатели и те, кто нет.

    Если выбросить из C++ указатели, и другие, не столь важные низкоуровневые конструкции, мы получим подобие одного из более поздних императивных языков: C#, Java. Непонимание указателей - основной барьер в изучении C++. К счастью, не для нас.


    Как уже много раз упоминалось ранее, вся ОЗУ разбита на пронумерованные ячейки размером в один байт. Переменные, что нам доводилось с Вами создавать, были локальными переменными. Локальность их заключалась во времени жизни. Время жизни локальной переменной - блок кода, в котором объявлена такая переменная(код, заключенный в фигурные скобки, будь-то тело условия, цикла или функции).


int main()

{
  int32_t a;

  {

    int8_t b;

    {

      int16_t c;
    }
  }

  return 0;

}

    Сначала создастся переменная "a". Затем переменная "b" и только потом "c". Но! Будьте внимательны! Сначала истечет время жизни переменной "c", затем будет разрушена переменная "b" и лишь потом "a". Такая модель создания-удаления переменных называется First In First Out(FIFO). Это в свою очередь и описывает работу стека. В данном контексте, стек - участок памяти, отведенный под локальные переменные. Размер стека по умолчанию небольшой: несколько мегабайт. Обычно, этого хватает с головой. Если Вам вдруг станет недоставать размера стека по умолчанию(по обоснованным причинам), то Вы уже будете на том уровне, где помощь с его увеличением от меня не потребуется. Вторая интересная вещь: чтобы управлять стеком, достаточно лишь иметь доступ к его верхушке. Представим, что изначально верхушка стека указывала на ячейку с номером 100 и смоделируем его работу из нашего простенького примера.


    Стек был пуст:


stack
[...] 103

[   ] 102
[   ] 101
[   ] 100
[...] 99

    Мы объявили локальную переменную "a", что заняла место четырех байт с 100 по 103 включительно. Верхушкой стека стал адрес 104. Когда мне вздумается объявить новую переменную, свободное место в памяти не придется искать, ведь вершина стека известна выполняемой среде.


stack [...] 105
[   ] 104
[   ] 103
[   ] 102
[   ] 101
[   ] 100 = a
[...] 99

    Объявление переменной "b", состоящей всего из одного байта:


stack [...] 106
[   ] 105
[   ] 104 = b
[   ] 103
[   ] 102
[   ] 101
[   ] 100 = a
[...] 99

    Верхушка сдвинулась на адрес с номером 105. Создание последней переменной по аналогии:


stack [...] 108
[   ] 107
[   ] 106
[   ] 105 = c
[   ] 104 = b
[   ] 103
[   ] 102
[   ] 101
[   ] 100 = a
[...] 99

    Как гласит правило работы стека: первым вошел - последним вышел. Так у нас и случилось. Переменные попали в стек в очередности "a", "b", "c", но удалятся из него в обратном порядке: "c", "b", "a". Ничего принципиально нового этот урок не учит, ведь объявляя переменные, Вы сами того не подозревая, использовали стек.


    Выводы: принцип работы стека прост, но весьма эффективен. Стек работает быстро, но его одного не хватит для решения большинства задач и об этом в следующей главе.

Комментариев нет:

Отправить комментарий