Для чего же нужны указатели?

Всем доброго времени суток. Никак не могу понять для чего нужны указатели? Объясните простым, человеческим языком, пожалуйста.
Сам я сначала думал чтобы через указатели изменять значения переменных, но зачем это делать через указатели, если можно напрямую данной переменной присвоить новое значение.
  • Вопрос задан
  • 9344 просмотра
Решения вопроса 1
Nipheris
@Nipheris Куратор тега C++
Ну и я тогда тоже попробую.

Посмотрим на вопрос с другой стороны.
Переменная - это контейнер для значения. Что нам вообще нужно для работы с переменной? Что нам нужно, чтобы считать/записать значение из/в нее? Нам нужны тип данных и адрес в памяти.
Тип данных - отдельная история, оставим пока его в стороне. Скажем только, что он определяет допустимые операции со значением и количество памяти, необходимое для хранения значения.
Поговорим об адресе. В языках, где доступна прямая работа с памятью, любая переменная имеет свой адрес в памяти. Также, в чуть более узком смысле, переменная находится в такой области памяти, в которую разрешена запись. Не имеет особого значения, какой структурой данных управляется эта память - стеком или кучей - важно, чтобы на момент использования эта память была доступна.
Корректный адрес в памяти - это и уникальный "ключ" переменной, ее отличительная черта. Работая с переменными, программист на низкоуровневом языке неизбежно работает с адресами.
Другой вопрос - это способ работы с адресом переменной. Когда вы создаете обычную локальную переменную, в работе с ней принимает участие компилятор. Когда вы пишете int a, компилятор (если не вдаваться в детали) размещает у себя в таблице идентификаторов пару: (имя_переменной, адрес_в_памяти). Обычная локальная переменная "а" (еще ее называют "автоматическая переменная") - способ создания переменной средствами компилятора. Компилятор освободит память, занимаемую этой переменной, когда она уйдет из области видимости. Однако, пока вам точно известно, что эта переменная "живет", вы можете совершенно спокойно получить ее адрес с помощью операции & - компилятор отдаст вам его из своей таблицы идентификаторов.

Но "переменные" в широком смысле можно создавать не только средствами компилятора, но и вручную с помощью malloc (Си) или new (С++). Эти динамические переменные живут столько, сколько вам нужно - вы их создаете, вам их и уничтожать. Об этих переменных компилятор ничего не знает, т.к. вы создаете их динамически во время выполнения программы. Для доступа к этим переменным вам также нужен адрес, но у компилятора его не попросишь: поэтому необходимо самому сохранять те адреса, что вернули вам функция malloc или оператор new. Этот адрес вы можете сохранить в ДРУГОЙ переменной, и такая переменная, хранящая адреса - и есть указатель (кроме того, если указатель не бестиповый (void*) то его тип (float*) еще и подсказывает нам тип переменной, на которую он указывает (float)).

Очень важно, что в указатель можно сохранить адрес ЛЮБОЙ переменной - как автоматической, которую вам создал компилятор, так и "ручной" - которую создали ВЫ с помощью malloc/new. И передать, например, этот адрес в функцию. Фактически, в языке Си указатели это и есть способ передачи САМОЙ ПЕРЕМЕННОЙ в функцию, а не ее ЗНАЧЕНИЯ на момент вызова. В C++ есть еще ссылки, но это отдельная история (ссылки - это указатель, "обернутый" в обычный идентификатор), по ним задайте отдельный вопрос.

если можно напрямую данной переменной присвоить новое значение.

Как раз таки "напрямую" вы не присвоите, т.к. у вас не может быть в одной области видимости ВСЕХ переменных, имеющихся в программе. Хотя бы потому, что у вас могут быть динамические переменные, и единственный способ работы с ними - работать через указатель.

Если вы никогда не работали с динамической памятью, вы можете спросить, какой смысл в "ручных" переменных, если для хранения их адреса нужна парная переменная-указатель? А вся фишка в том, что адрес динамически созданной переменной также можно хранить в динамически созданном указателе. Тут-то и открывается вся бесконечная свобода построения динамических структур данных. Если вы не слышали про связный список, то самое время почитать хорошую книгу с примерами. В одном ответе этого не расскажешь, это основы программирования.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
Daemon23RUS
@Daemon23RUS
Например у вас в программе используется переменная, Вы вызывая функцию/процедуру передаете копию этой переменной, изменения внесенные в процедуре, не отразятся на основной переменной. Передавая указатель процедура может изменять значение основной переменной.
Это если не вдаватся в массу деталей...
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
Хорошо, попробую. Вот у нас есть файл на каком-нибудь NAS. Мы хотим его переслать товарищу. Мы можем…
• приложить файл к сообщению, тогда у нас будут два независимых файла. Просто и надёжно, недостатка два. 1) Файл копируется, это трудоёмко. 2) Копия живёт своей жизнью, и изменения в копии не затронут оригинал. Это передача по копии.
• дать имя файла. Один изменяет файл — второй прочитает изменение, и никакого копирования. Недостаток — надо договариваться, кто владеет файлом (т.е. уничтожит его, когда тот не будет нужен). Имя файла — это и есть указатель.
Метафора неполная, ведь файловая система может сказать, есть ли файл, а в памяти указатель на отсутствующий «файл» — это Access Violation. Да и «учёток» в памяти нет. Тем не менее…
Ответ написан
Комментировать
@sitev_ru
sitev.ru - мой блог ...
Это как ярлык в виндоус! Можно обратиться напрямую к файлу, а можно разместить ярлык, например, на рабочем столе. В ярлыке будет указано, где находится файл.

Так и с указателями...

Где-то находиться переменная, а у указателе находится адрес расположения переменной в памяти. А теперь уже зависит от ситуации, обращаться к переменной напрямую или через указатель...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы