Дональд Кнут считает указатели одним из главных изобретений в языке программирования Си. И это не просто так.
Вам известно, что любая переменная - это именованная область памяти. Все пространство памяти проиндексировано. У каждого байта есть свой адрес.
Рассмотрим пример:
int x = 94;
std::cout << &x; // --> 0x7ffe53575c6c
Переменная x имеет значение 94. Но когда я вывел на консоль &x, то получил 0x7ffe53575c6c. У вас это значение, скорее всего, будет другим.
Что это за значение ? 0x7ffe53575c6c - адрес переменной x, выведенный в 16-ной форме. Его фактическое значение и смысл для нас не интересен.
Важно: у ЛЮБОЙ переменной есть адрес.
Адрес переменной - значение (число). Но ведь мы умеем хранить значения? Используем для этого переменную особого типа - указатель:
int x = 94;
int* pX = &x; // Записываем в pX адрес переменной x
std::cout << pX; // --> 0x7ffd09760ee4
Важно: указатель - переменная, которая может хранить адрес другой переменной.
Синтаксис int* pX означает, что pX может хранить адрес переменной типа int. Мы явно говорим, что указатель создается именно для int. Это необходимо, чтобы затем мы смогли извлечь значение, на которое указывает указатель:
int x = 94;
int* pX = &x;
std::cout << *pX; // --> 94
Если pX - адрес переменной x, то *pX - значение, которое расположено по этому адресу. Данная операция называется разыменованием указателя.
Важно: x и *pX - абсолютно ЭКВИВАЛЕНТНЫ. Они представляют собой одно и то же значение, хранимое по одному и тому же адресу.
Следствие: если мы меняем значение x, то меняется и значение *pX, и наоборот:
int x = 94;
int* pX = &x;
std::cout << "x=" << x << "; *pX=" << *pX << std::endl; // --> x=94; *pX=94
x = 18;
std::cout << "x=" << x << "; *pX=" << *pX << std::endl; // --> x=18; *pX=18
*pX = -33;
std::cout << "x=" << x << "; *pX=" << *pX << std::endl; // --> x=-33; *pX=-33
Чтобы закрепить знания, советую обратиться к примерам, которые полностью или во многом основаны на использовании указателей:
Anonymous
ну ты дал такие основы рассказывать, ведь тебя не нубасы читают