Указатель (тип данных)

Поделись знанием:
Перейти к: навигация, поиск

Указатель (англ. pointer) — переменная, диапазон значений которой состоит из адресов ячеек памяти или специального значения — нулевого адреса. Последнее используется для указания того, что в данный момент указатель не ссылается ни на одну из допустимых ячеек.

Русское название термин получил по аналогии с дорожными указателями, на них обозначают направление и расстояние до того или иного города.К:Википедия:Статьи без источников (тип: не указан)[источник не указан 2794 дня]





Область применения

Указатели применяются в двух сферах:

  • Работа в системе косвенной адресации (как в языках ассемблера). Одним из её преимуществ можно назвать экономию памяти. Делая указатель на файл, мы читаем его с диска, а не загружаем в ОЗУ. Передавая указатель на переменную в функцию мы не делаем копию этой переменной, а редактируем её напрямую[1]. Указатели используют для хранения адресов точек входа для так называемых подпрограмм в процедурном программировании и для подключения динамических подключаемых библиотек.
  • Динамическое управление памятью. В таком случае выделяется место в так называемой куче (динамической памяти), а переменные, для которых память выделена таким образом, называются динамическими[2]. В языке Си нет понятия строковой переменной, так что для строк часто используют указатель на массив символов.

Действия над указателями

Языки программирования, в которых предусмотрен тип указателей, содержат, как правило, две основные операции над ними: присваивание и разыменование. Первая присваивает указателю некоторый адрес. Вторая служит для обращения к значению в памяти, на которое указывает указатель. Разыменование может быть явным и неявным; в большинстве современных языков программирования разыменование происходит только при явном указании[чего?]К:Википедия:Статьи без источников (тип: не указан)[источник не указан 2784 дня].

Пример работы с указателями в языке Си:

int  n  = 6;    // Объявление переменной n типа int и присваивание ей значения 6
int *pn = malloc( sizeof ( int ) ); // Объявление указателя pn и выделение под него памяти
    *pn = 5;    // Разыменование указателя и присваивание значения 5
     n = *pn;   // Присваивание n того значения (5), на которое указывает pn
     free(pn);  // Освобождение занятой памяти
     pn = &n;   // Присваивание указателю pn адреса переменной n (указатель будет ссылаться на n)
     n = 7;     // *pn тоже стало равно 7

Унарный оператор & возвращает адрес переменной, а оператор * используется для разыменования:

int sourceNum1 = 100;
int sourceNum2 = 200;
int* pNum1 = &sourceNum1;
int* pNum2 = &sourceNum2;
printf("Pointer value of 1-%d, 2-%d\n", *pNum1, *pNum2);  
pNum1 = pNum2;
printf("Pointer value of 1-%d, 2-%d\n", *pNum1, *pNum2);

В случае, если указатель хранит адрес какого-либо объекта, то говорят, что указатель ссылается или указывает на этот объект.

Языки, предусматривающие использование указателей для динамического распределения памяти, должны содержать оператор явного размещения переменных в памяти. В некоторых языках помимо этого оператора предусмотрен ещё и оператор явного удаления переменных из памяти. Обе эти операции часто принимают форму встроенных подпрограмм (функции malloc и free в Си, операторы new и delete в C++ и т. п.). При использовании простого, а не умного указателя следует всегда своевременно удалять переменную из памяти, дабы избежать утечки памяти.

Нулевой указатель

Нулевой указатель — это указатель, хранящий специальное значение, показывающее, что данная переменная-указатель не ссылается (не указывает) ни на какой объект. В языках программирования он представлен особой константой[3]:

Основные проблемы применения

Указателями сложно управлять. Достаточно легко записать в указатель неправильное значение, что может вызвать трудновоспроизводимую ошибку. Например, вы случайно поменяли адрес указателя в памяти, или неправильно выделили под информацию память и тут вас может ожидать сюрприз: другая очень важная переменная, которая используется только внутри программы будет перезаписана..Понять, где именно находится ошибка и воспроизвести её будет нелегко, а устранение таких ошибок — не всегда тривиальная задача, иногда приходится переписывать существенную часть программы)[5].

Для решения части проблем есть методы предохранения и страховки:

Инициализируйте указатели

Пример ошибки с неинициализированным указателем:

/* программа неверна. */
int main (void)
{
    int х, *р; // Выделилась память под x, но не под *p
    х = 10;    // В память записано 10
    *р = х;    // 10 записывается в неопределённое место в памяти, что может привести к аварийному завершению программы.
    return 0;
}

В такой маленькой программе проблема может остаться незамеченной. Но, когда программа разрастется, то внезапно может выясниться, что переменная записана между других блоков данных, важных для программы. Чтобы избежать такой ситуации, просто инициализируйте указатель[5].

Используйте указатели правильно

Неправильное использование указателя:

#include <stdio.h>
/* программа неверна */
int main(void)
{
    int x, *p;
    x = 10;
    p = x;
    printf ("%d", *p);
    return 0;
}

Вызов printf() не выводит значения х, которое равно 10, на экран. Вместо этого выводится некоторое неизвестное значение — это результат неправильного использование оператора присваивания (р = х;). Этот оператор присваивает значение 10 указателю р, который должен содержать адрес, а не значение. К счастью, ошибка в данной программе обнаруживается компилятором — он выдаёт предупреждение о необычном преобразовании указателя. Для устранения ошибки следует написать p = &х;[5].

Правильное использование указателя

  • старайтесь инициализировать переменные сразу при объявлении (int x = 10;);
  • не смешивайте указатели с обычными переменными (например, int x, *p, y, *y_ptr;);
#include <stdio.h>
int main(void)
{
    int x = 10;
    int *p = &x;
    printf ("%d", *p);
    return 0;
}

Утечка памяти

Утечка памяти — процесс неконтролируемого уменьшения объёма свободной оперативной памяти (RAM) компьютера, связанный с ошибками в работающих программах, вовремя не освобождающих ненужные уже участки памяти, или с ошибками системных служб контроля памяти.

char *pointer = NULL;
int i = 0;
for( i = 0; i < 10; i++ )
{
    pointer = (char *)malloc(100); // Память выделяет 10 раз
}
free(pointer); // А освобождается только в последнем случае

Сравнение указателей

Адреса в памяти, присвоенные указателям, можно сравнивать. Сравнения вида pNum1 < pNum2 и pNum1 > pNum2 часто используются для последовательного перебора элементов массива в цикле: pNum1 соответствует текущему положению в памяти, а pNum2 — концу массива. pNum1 == pNum2 вернёт истину в том случае, если оба указателя указывают на одну ячейку памяти.

Адресная арифметика

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

Типичные операции адресной арифметики:

int* p; // Допустим, p указывает на адрес 200
p++;    // После инкрементации она указывает на 200 + sizeof(int) = 204
p--;    // Сейчас она вновь указывает на 200.

Умный указатель

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

Указатель в биологии человека

Мозг использует группы клеток, похожие на указатели, для решения некоторых задач, связанных с запоминанием новой информации[6].

Напишите отзыв о статье "Указатель (тип данных)"

Примечания

  1. [devprog.wordpress.com/2009/01/15/%D1%83%D0%BA%D0%B0%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D0%B8-%D0%B2-%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B8/ Для чего используются указатели?]. Проверено 20 февраля 2013. [www.webcitation.org/6Eib7hR46 Архивировано из первоисточника 26 февраля 2013].
  2. [dvo.sut.ru/libr/cvti/i618buz/14.htm 14.1. Распределение памяти]. — «Адрес начала выделенной памяти возвращается в точку вызова функции и записывается в переменную-указатель. Созданная таким образом переменная называется динамической переменной.»  Проверено 22 февраля 2013. [www.webcitation.org/6EibKd5ha Архивировано из первоисточника 26 февраля 2013].
  3. [c-faq.com/null/null1.html Question 5.1]. comp.lang.c Frequently Asked Questions. Проверено 20 февраля 2013. [www.webcitation.org/6EibLyMXR Архивировано из первоисточника 26 февраля 2013].
  4. [www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf A name for the null pointer: nullptr] (англ.). JTC1.22.32. JTC1/SC22/WG21 — The C++ Standards Committee (2 October 2007). Проверено 4 октября 2010. [www.webcitation.org/65NGO4mjK Архивировано из первоисточника 11 февраля 2012].
  5. 1 2 3 [www.c-cpp.ru/books/problemy-svyazannye-s-ukazatelyami Проблемы, связанные с указателями]. Проверено 22 февраля 2013. [www.webcitation.org/6EibNbcCc Архивировано из первоисточника 26 февраля 2013].
  6. [ria.ru/science/20130923/965317404.html Мозг использует приемы из программирования для решения новых задач]. РИА Новости (23 сентября 2013). Проверено 13 сентября 2016.


Отрывок, характеризующий Указатель (тип данных)

Княжне, видимо, досадно было, что не на кого было сердиться. Она, что то шепча, присела на стул.
– Но вам это неправильно доносят, – сказал Пьер. – В городе все тихо, и опасности никакой нет. Вот я сейчас читал… – Пьер показал княжне афишки. – Граф пишет, что он жизнью отвечает, что неприятель не будет в Москве.
– Ах, этот ваш граф, – с злобой заговорила княжна, – это лицемер, злодей, который сам настроил народ бунтовать. Разве не он писал в этих дурацких афишах, что какой бы там ни был, тащи его за хохол на съезжую (и как глупо)! Кто возьмет, говорит, тому и честь и слава. Вот и долюбезничался. Варвара Ивановна говорила, что чуть не убил народ ее за то, что она по французски заговорила…
– Да ведь это так… Вы всё к сердцу очень принимаете, – сказал Пьер и стал раскладывать пасьянс.
Несмотря на то, что пасьянс сошелся, Пьер не поехал в армию, а остался в опустевшей Москве, все в той же тревоге, нерешимости, в страхе и вместе в радости ожидая чего то ужасного.
На другой день княжна к вечеру уехала, и к Пьеру приехал его главноуправляющий с известием, что требуемых им денег для обмундирования полка нельзя достать, ежели не продать одно имение. Главноуправляющий вообще представлял Пьеру, что все эти затеи полка должны были разорить его. Пьер с трудом скрывал улыбку, слушая слова управляющего.
– Ну, продайте, – говорил он. – Что ж делать, я не могу отказаться теперь!
Чем хуже было положение всяких дел, и в особенности его дел, тем Пьеру было приятнее, тем очевиднее было, что катастрофа, которой он ждал, приближается. Уже никого почти из знакомых Пьера не было в городе. Жюли уехала, княжна Марья уехала. Из близких знакомых одни Ростовы оставались; но к ним Пьер не ездил.
В этот день Пьер, для того чтобы развлечься, поехал в село Воронцово смотреть большой воздушный шар, который строился Леппихом для погибели врага, и пробный шар, который должен был быть пущен завтра. Шар этот был еще не готов; но, как узнал Пьер, он строился по желанию государя. Государь писал графу Растопчину об этом шаре следующее:
«Aussitot que Leppich sera pret, composez lui un equipage pour sa nacelle d'hommes surs et intelligents et depechez un courrier au general Koutousoff pour l'en prevenir. Je l'ai instruit de la chose.
Recommandez, je vous prie, a Leppich d'etre bien attentif sur l'endroit ou il descendra la premiere fois, pour ne pas se tromper et ne pas tomber dans les mains de l'ennemi. Il est indispensable qu'il combine ses mouvements avec le general en chef».
[Только что Леппих будет готов, составьте экипаж для его лодки из верных и умных людей и пошлите курьера к генералу Кутузову, чтобы предупредить его.
Я сообщил ему об этом. Внушите, пожалуйста, Леппиху, чтобы он обратил хорошенько внимание на то место, где он спустится в первый раз, чтобы не ошибиться и не попасть в руки врага. Необходимо, чтоб он соображал свои движения с движениями главнокомандующего.]
Возвращаясь домой из Воронцова и проезжая по Болотной площади, Пьер увидал толпу у Лобного места, остановился и слез с дрожек. Это была экзекуция французского повара, обвиненного в шпионстве. Экзекуция только что кончилась, и палач отвязывал от кобылы жалостно стонавшего толстого человека с рыжими бакенбардами, в синих чулках и зеленом камзоле. Другой преступник, худенький и бледный, стоял тут же. Оба, судя по лицам, были французы. С испуганно болезненным видом, подобным тому, который имел худой француз, Пьер протолкался сквозь толпу.
– Что это? Кто? За что? – спрашивал он. Но вниманье толпы – чиновников, мещан, купцов, мужиков, женщин в салопах и шубках – так было жадно сосредоточено на то, что происходило на Лобном месте, что никто не отвечал ему. Толстый человек поднялся, нахмурившись, пожал плечами и, очевидно, желая выразить твердость, стал, не глядя вокруг себя, надевать камзол; но вдруг губы его задрожали, и он заплакал, сам сердясь на себя, как плачут взрослые сангвинические люди. Толпа громко заговорила, как показалось Пьеру, – для того, чтобы заглушить в самой себе чувство жалости.
– Повар чей то княжеский…
– Что, мусью, видно, русский соус кисел французу пришелся… оскомину набил, – сказал сморщенный приказный, стоявший подле Пьера, в то время как француз заплакал. Приказный оглянулся вокруг себя, видимо, ожидая оценки своей шутки. Некоторые засмеялись, некоторые испуганно продолжали смотреть на палача, который раздевал другого.
Пьер засопел носом, сморщился и, быстро повернувшись, пошел назад к дрожкам, не переставая что то бормотать про себя в то время, как он шел и садился. В продолжение дороги он несколько раз вздрагивал и вскрикивал так громко, что кучер спрашивал его:
– Что прикажете?
– Куда ж ты едешь? – крикнул Пьер на кучера, выезжавшего на Лубянку.
– К главнокомандующему приказали, – отвечал кучер.
– Дурак! скотина! – закричал Пьер, что редко с ним случалось, ругая своего кучера. – Домой я велел; и скорее ступай, болван. Еще нынче надо выехать, – про себя проговорил Пьер.
Пьер при виде наказанного француза и толпы, окружавшей Лобное место, так окончательно решил, что не может долее оставаться в Москве и едет нынче же в армию, что ему казалось, что он или сказал об этом кучеру, или что кучер сам должен был знать это.
Приехав домой, Пьер отдал приказание своему все знающему, все умеющему, известному всей Москве кучеру Евстафьевичу о том, что он в ночь едет в Можайск к войску и чтобы туда были высланы его верховые лошади. Все это не могло быть сделано в тот же день, и потому, по представлению Евстафьевича, Пьер должен был отложить свой отъезд до другого дня, с тем чтобы дать время подставам выехать на дорогу.
24 го числа прояснело после дурной погоды, и в этот день после обеда Пьер выехал из Москвы. Ночью, переменя лошадей в Перхушкове, Пьер узнал, что в этот вечер было большое сражение. Рассказывали, что здесь, в Перхушкове, земля дрожала от выстрелов. На вопросы Пьера о том, кто победил, никто не мог дать ему ответа. (Это было сражение 24 го числа при Шевардине.) На рассвете Пьер подъезжал к Можайску.
Все дома Можайска были заняты постоем войск, и на постоялом дворе, на котором Пьера встретили его берейтор и кучер, в горницах не было места: все было полно офицерами.
В Можайске и за Можайском везде стояли и шли войска. Казаки, пешие, конные солдаты, фуры, ящики, пушки виднелись со всех сторон. Пьер торопился скорее ехать вперед, и чем дальше он отъезжал от Москвы и чем глубже погружался в это море войск, тем больше им овладевала тревога беспокойства и не испытанное еще им новое радостное чувство. Это было чувство, подобное тому, которое он испытывал и в Слободском дворце во время приезда государя, – чувство необходимости предпринять что то и пожертвовать чем то. Он испытывал теперь приятное чувство сознания того, что все то, что составляет счастье людей, удобства жизни, богатство, даже самая жизнь, есть вздор, который приятно откинуть в сравнении с чем то… С чем, Пьер не мог себе дать отчета, да и ее старался уяснить себе, для кого и для чего он находит особенную прелесть пожертвовать всем. Его не занимало то, для чего он хочет жертвовать, но самое жертвование составляло для него новое радостное чувство.


24 го было сражение при Шевардинском редуте, 25 го не было пущено ни одного выстрела ни с той, ни с другой стороны, 26 го произошло Бородинское сражение.
Для чего и как были даны и приняты сражения при Шевардине и при Бородине? Для чего было дано Бородинское сражение? Ни для французов, ни для русских оно не имело ни малейшего смысла. Результатом ближайшим было и должно было быть – для русских то, что мы приблизились к погибели Москвы (чего мы боялись больше всего в мире), а для французов то, что они приблизились к погибели всей армии (чего они тоже боялись больше всего в мире). Результат этот был тогда же совершении очевиден, а между тем Наполеон дал, а Кутузов принял это сражение.
Ежели бы полководцы руководились разумными причинами, казалось, как ясно должно было быть для Наполеона, что, зайдя за две тысячи верст и принимая сражение с вероятной случайностью потери четверти армии, он шел на верную погибель; и столь же ясно бы должно было казаться Кутузову, что, принимая сражение и тоже рискуя потерять четверть армии, он наверное теряет Москву. Для Кутузова это было математически ясно, как ясно то, что ежели в шашках у меня меньше одной шашкой и я буду меняться, я наверное проиграю и потому не должен меняться.
Когда у противника шестнадцать шашек, а у меня четырнадцать, то я только на одну восьмую слабее его; а когда я поменяюсь тринадцатью шашками, то он будет втрое сильнее меня.
До Бородинского сражения наши силы приблизительно относились к французским как пять к шести, а после сражения как один к двум, то есть до сражения сто тысяч; ста двадцати, а после сражения пятьдесят к ста. А вместе с тем умный и опытный Кутузов принял сражение. Наполеон же, гениальный полководец, как его называют, дал сражение, теряя четверть армии и еще более растягивая свою линию. Ежели скажут, что, заняв Москву, он думал, как занятием Вены, кончить кампанию, то против этого есть много доказательств. Сами историки Наполеона рассказывают, что еще от Смоленска он хотел остановиться, знал опасность своего растянутого положения знал, что занятие Москвы не будет концом кампании, потому что от Смоленска он видел, в каком положении оставлялись ему русские города, и не получал ни одного ответа на свои неоднократные заявления о желании вести переговоры.