tritonov01
@tritonov01
Изучаю С++

Что такое указатели в С++?

Здравствуйте. Недавно я на сайте прочёл статью про указатели. Там мне объяснили, что такое указатели и для чего они применяются.

Сейчас процитирую текст с сайта:
При выполнении любой программы, все необходимые для ее работы данные должныбыть загружены в оперативную память компьютера. Для обращения к переменным, находящимся в памяти, используются специальные адреса, которые записываются в шестнадцатеричном виде, например 0x100 или 0x200.

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

Если мы объявляем переменные статично, так как мы делали в предыдущих уроках, они остаются в памяти до того момента, как программа завершит свою работу, а после чего уничтожаются.

Такой подход может быть приемлем в простых примерах и несложных программах, которые не требуют большого количества ресурсов. Если же наш проект является огромным программным комплексом с высоким функционалом, объявлять таким образом переменные, естественно, было бы довольно не умно.

Можете себе представить, если бы небезызвестная Battlefield 3 использовала такой метод работы с данными? В таком случае, самым заядлым геймерам пришлось бы перезагружать свои высоконагруженные системы кнопкой reset после нескольких секунд работы игры.

Дело в том, что играя в тот же Battlefield, геймер в каждый новый момент времени видит различные объекты на экране монитора, например сейчас я стреляю во врага, а через долю секунды он уже падает убитым, создавая вокруг себя множество спецэффектов, таких как пыль, тени, и т.п.

Естественно, все это занимает какое-то место в оперативной памяти компьютера. Если не уничтожать неиспользуемые объекты, очень скоро они заполнят весь объем ресурсов ПК.

По этим причинам, в большинстве языков, в том числе и C/C++, имеется понятие указателя. Указатель — это переменная, хранящая в себе адрес ячейки оперативной памяти, например 0x100.

Мы можем обращаться, например к массиву данных через указатель, который будет содержать адрес начала диапазона ячеек памяти, хранящих этот массив.

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


Мой знакомый сказал, что это все фигня и они несут чушь. Я немного запутался. Можете высказать свою версию на счёт указателей, пожалуйста!
  • Вопрос задан
  • 190 просмотров
Решения вопроса 1
@Mercury13
Программист на «си с крестами» и не только
Если переменных в памяти потребуется слишком большое количество, которое не сможет вместить в себя сама аппаратная часть, произойдет перегрузка системы или её зависание.

Либо будет дичайше свопить, либо отказ с нехваткой памяти. А уж как этот отказ устроен — через «падение», зависание, какое-то сообщение… — это может быть по-разному.

Можете себе представить, если бы небезызвестная Battlefield 3 использовала такой метод работы с данными? В таком случае, самым заядлым геймерам пришлось бы перезагружать свои высоконагруженные системы кнопкой reset после нескольких секунд работы игры.

Нет. Памяти было бы отведено с запасом уже при запуске, и даже небольшая игра требовала бы многие и многие гигабайты памяти, а Battlefield бы просто не запускался даже на топовых ПК. И часть настроек качества не имела бы смысла — изначально, уже при загрузке EXE’шника, выделено памяти с запасом и никак не ужмёшься. Но нет худа без добра — половины глюков и вылетов не существовало бы. Так что мелкие игры, способные бегать на 99% современных и не очень ПК и потому не имеющие настроек качества, этим механизмом вполне пользуются.

Разрешите попиариться — пишу программу «Юникодия», энциклопедию символов — таблица на 140 тыс. позиций (количество существующих на данный момент символов) занимает большую часть EXE’шника. А таблица на 1,1 млн (ёмкость Юникода) восьмибайтовых указателей тоже выделена статически, но места в EXE’шнике не занимает и заполняется на старте. Таким образом мы может легко пробежаться по всем символам, и можем по коду символа найти его запись.

Если не уничтожать неиспользуемые объекты, очень скоро они заполнят весь объем ресурсов ПК.

Указатели — это не только про уничтожение памяти, но и про выделение.

Но главное, что вы поняли одно: указатель — это адрес в памяти плюс вкомпилированный в программу тип (на железном уровне типов нет).

И второе: по указателю мы можем получить доступ к объекту, чьего имени мы не знаем (как у меня в таблице символов) или он безымянный (если он выделен динамически, при работе программы, а не вкомпилирован в неё).
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Adamos
@Adamos
Написана дичь, не имеющая никакого отношения к реальности.
Причем стиль написания говорит о низкой грамотности автора.
Читайте нормальные учебники, а не отсебятину.
Ответ написан
Комментировать
@res2001
Developer, ex-admin
Из всего написанного по сути сказано только:
Указатель — это переменная, хранящая в себе адрес ячейки оперативной памяти

остальное - какой-то шлак.

Добавлю от себя про указатели:
Память в компьютере адресуется побайтово.
Биты внутри байта адресовать через указатель нельзя.
Адрес - это просто беззнаковое целое число - номер байта в памяти.
В 32битных процах максимально доступно 2^32 байта памяти, в 64битных - 2^64.
Соответственно для хранения адреса в 32битных системах нужно 32 бита, т.е. 4 байта, в 64битных - 64 бита, т.е. 8 байт. Таким образом, в зависимости от разрядности процессора меняется размер указателя.

Когда некий объект (строка, число, и прочее) сохранен в памяти он не имеет типа - это просто набор байт некоторой длины. Типизацией занимается программа. Например в процессоре существуют наборы арифметических команд для целых 1 байтовых переменных, 2 байтовых, 4 и 8 байтовых (отдельно для знаковых и беззнаковых). Т.е. это реально разные ассемблерные инструкции (например для сложения). Таким образом задавая тип указателя, вы говорите компилятору, что к памяти, адресуемой этим указателем, нужно применять инструкции для этого типа данных.
Для типизированных указателей можно использовать адресную арифметику, потому что компилятору известен размер типа. Для не типизированных указателей (void*) адресная арифметика не возможна.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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