[FAQ] Указатели - Форум Cheat-Master.ru
  • Страница 1 из 1
  • 1
Модератор форума: Sanoxxx, Alowir  
[FAQ] Указатели
eastwood63 Дата: Пятница, 25.12.2015, 21:16 | Сообщение # 1
Боец
Сообщений: 283
Статус: Offline
Указатель – переменная, значением которой является адрес ячейки памяти. То есть указатель ссылается на блок данных из области памяти, причём на самое его начало. Указатель может ссылаться на переменную или функцию. Для этого нужно знать адрес переменной или функции. Так вот, чтобы узнать адрес конкретной переменной в С++ существует унарная операция взятия адреса &. Такая операция извлекает адрес объявленных переменных, для того, чтобы его присвоить указателю.

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

Код
//объявление указателя
/*тип данных*/  * /*имя указателя*/;


Принцип объявления указателей такой же, как и принцип объявления переменных. Отличие заключается только в том, что перед именем ставится символ звёздочки *. Визуально указатели отличаются от переменных только одним символом. При объявлении указателей компилятор выделяет несколько байт памяти, в зависимости от типа данных отводимых для хранения некоторой информации в памяти. Чтобы получить значение, записанное в некоторой области, на которое ссылается указатель нужно воспользоваться операцией разыменования указателя *. Необходимо поставить звёздочку перед именем и получим доступ к значению указателя. Разработаем программу, которая будет использовать указатели.

Код
// pointer1.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    int var = 123; // инициализация переменной var числом 123
    int *ptrvar = &var; // указатель на переменную var (присвоили адрес переменной указателю)
    cout << "&var    = " << &var << endl;// адрес переменной var содержащийся в памяти, извлечённый операцией взятия адреса
    cout << "ptrvar  = " << ptrvar << endl;// адрес переменной var, является значением указателя ptrvar
    cout << "var     = " << var << endl; // значение в переменной var
    cout << "*ptrvar = " << *ptrvar << endl; // вывод значения содержащегося в переменной var через указатель, операцией разименования указателя
    system("pause");
    return 0;
}


В строке 10 объявлен и инициализирован адресом переменной var указатель ptrvar. Можно было сначала просто объявить указатель, а потом его инициализировать, тогда были бы две строки:

Код
int *ptrvar;        // объявление указателя
     ptrvar = &var; // инициализация указателя


Итак, программа показала, что строки 11 и 12 выводят идентичный адрес, то есть адрес переменной var, который содержится в указателе ptrvar. Тогда как операция разыменования указателя *ptrvar обеспечивает доступ к значению, на которое ссылается указатель.

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

Код
// pointer.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    int var1 = 123; // инициализация переменной var1 числом 123
    int var2 = 99; // инициализация переменной var2 числом 99
    int *ptrvar1 = &var1; // указатель на переменную var1
    int *ptrvar2 = &var2; // указатель на переменную var2
    cout << "var1    = " << var1 << endl;
    cout << "var2    = " << var2 << endl;
    cout << "ptrvar1 = " << ptrvar1 << endl;
    cout << "ptrvar2 = " << ptrvar2 << endl;
    if (ptrvar1 > ptrvar2) // сравниваем значения указателей, то есть адреса переменных
        cout << "ptrvar1 > ptrvar2" << endl;
    if (*ptrvar1 > *ptrvar2) // сравниваем значения переменных, на которые ссылаются указатели
        cout << "*ptrvar1 > *ptrvar2" << endl;
    system("pause");
    return 0;
}


Указатели на указатели


Указатели могут ссылаться на другие указатели. При этом в ячейках памяти, на которые будут ссылаться первые указатели, будут содержаться не значения, а адреса вторых указателей. Число символов * при объявлении указателя показывает порядок указателя. Чтобы получить доступ к значению, на которое ссылается указатель его необходимо разыменовывать соответствующее количество раз. Разработаем программу, которая будет выполнять некоторые операции с указателями порядка выше первого.


Код
// pointer.cpp: определяет точку входа для консольного приложения.
#include "stdafx.h"
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    int var = 123; // инициализация переменной var числом 123
    int *ptrvar = &var; // указатель на переменную var
    int **ptr_ptrvar = &ptrvar; // указатель на указатель на переменную var
    int ***ptr_ptr_ptrvar = &ptr_ptrvar;
    cout << " var\t\t= " << var << endl;
    cout << " *ptrvar\t= " << *ptrvar << endl;
    cout << " **ptr_ptrvar   = " << **ptr_ptrvar << endl; // два раза разименовываем указатель, так как он второго порядка
    cout << " ***ptr_ptrvar  = " << ***ptr_ptr_ptrvar << endl; // указатель третьего порядка
    cout << "\n ***ptr_ptr_ptrvar -> **ptr_ptrvar -> *ptrvar ->      var -> "<< var << endl;
    cout << "\t  " << &ptr_ptr_ptrvar<< " -> " << "    " << &ptr_ptrvar << " ->" << &ptrvar << " -> " << &var << " -> " << var << endl;
    system("pause");
    return 0;
}


Указатели на функции


Указатели могут ссылаться на функции. Имя функции, как и имя массива само по себе является указателем, то есть содержит адрес входа.

Код
// объявление указателя на функцию
/*тип данных*/ (* /*имя указателя*/)(/*список аргументов функции*/);


Тип данных определяем такой, который будет возвращать функция, на которую будет ссылаться указатель. Символ указателя и его имя берутся в круглые скобочки, чтобы показать, что это указатель, а не функция, возвращающая указатель на определённый тип данных. После имени указателя идут круглые скобки, в этих скобках перечисляются все аргументы через запятую как в объявлении прототипа функции. Аргументы наследуются от той функции, на которую будет ссылаться указатель. Разработаем программу, которая использует указатель на функцию. Программа должна находить НОД – наибольший общий делитель. НОД – это наибольшее целое число, на которое без остатка делятся два числа, введенных пользователем. Входные числа также должны быть целыми.

Код
// pointer_onfunc.cpp: определяет точку входа для консольного приложения.

#include "stdafx.h"
#include <iostream>
using namespace std;
int nod(int, int ); // прототип указываемой функции
int main(int argc, char* argv[])
{
    int (*ptrnod)(int, int); // объявление указателя на функцию
    ptrnod=nod; // присваиваем адрес функции указателю ptrnod
    int a, b;
    cout << "Enter first number: ";
    cin >> a;
    cout << "Enter second number: ";
    cin >> b;
    cout << "NOD = " << ptrnod(a, b) << endl; // обращаемся к функции через указатель
    system("pause");
    return 0;
}
int nod(int number1, int number2) // рекурсивная функция нахождения наибольшего общего делителя НОД
{
    if ( number2 == 0 ) //базовое решение
        return number1;
    return nod(number2, number1 % number2); // рекурсивное решение НОД
}


[AHK] Все биндеры для всех фракций DRP, ARP, SRP
[DRP] Ездим на такси бесплатно
[ARP] ЧИТЕРИМ ГАН С БОМЖА (1ЛВЛ)
[DRP] Оплачиваем дом с твинка
[DRP] Лучшая работа для 1 уровня
[CLEO] Мои темы с разработками
[Cheater] Все мои видео читинга
  • Страница 1 из 1
  • 1
Поиск:
Статистика Форума
Лучшие пользователи
Admin [39113]

GеNius [7210]

[CM]Russel [5557]

kenlo763 [4952]

[CM]AGRESSOR [4639]

Snake_Firm [4452]

Сэс [4416]

Artem_Buero [4223]

[CM]Durman [3204]

[CM]Рафаэль [3080]

iMaddy [2855]

sky_Woker [2854]

getrekt [2745]

Новые пользователи
PUPS12124 [02:09]

Bioksit [00:15]

Dafdaf [23:27]

ячеченец [21:00]

balbesbizad [12:02]

cpark [11:40]

Mario_Imperator [11:33]

leonovichstas97 [22:40]

ubeyefudu [18:53]

zheniakuzma [17:47]

Moonberg [16:04]

tamararl6 [15:04]

consuelobm3 [08:03]