Использование указателей
В языке С++ широко используются данные,которые называются указателями. Указатели — это переменные, которые содержат адрес памяти, распределенной для другой переменной. Все переменные, рассмотренные до сих пор, хранили какие-то значения (данные). Эти данные могли быть разных типов: символьного, целого, вещественного и т.д. При объявлении переменной - указателя необходимо указать тип данных, адрес которых будет содержать переменная, и имя указателя с предшествующей звездочкой. Общий формат описания указателя следующий: тип * имя; где тип — тип значений, на который будет указывать указатель; имя — имя переменной-указателя; * — означает операцию над типом, которая читается "указатель" на тип. Приведем примеры определений указателей: int *pn; // указатель на целое значение; float *pf1, *pf2 ; // два указателя на вещественные значения; Указатели не привязывают данные к какому-нибудь определенному имени переменной и могут содержать адрес любого неименованного значения. Существует адресная константа NULL , которая означает "пустой" адрес. В языке С++ имеется всего два оператора, относящихся к указателям:
“&” — оператор " адрес значения "; “* “ — оператор "значение по адресу". Оператор "*" , используемый вместе с указателями, извлекает значение, на которое указывает переменная, расположенная непосредственно после него. Оператор "&" , используемый вместе с указателями, возвращает адрес переменной, расположенной непосредственно после него. Указатели можно объявить одним из следующих способов: <тип.> *ptr; <тип> *ptr = <переменная - указатель>; <тип> *ptr =&<имя переменной>; // адрес переменной В программе это может выглядеть следующим образом: int *ptx ,b ; float y; // объявлены переменная - указатель ptx иобычные переменные b и y; float *sp = &y; // указателю sp присваивается адрес переменной y float *p = sp; // указателю p присваивается значение (адрес значения), // которое содержится в переменной sp, т.е. адрес переменной y. При объявлении указателей символ "*" может располагаться либо перед именем указателя либо записываться сразу после объявления типа указателя и распространяет свое действие только на одну переменную - указатель, перед которой он стоит, например: long *pt; long* Uk; int * ki, x, h ; // объявление описаний В случае необходимости описания указателя на ячейку произвольного типа, вместо идентификатора типа записывается слово void, например:
void *p, *pt; // описаны два указателя на произвольный тип данных Прежде чем использовать указатель в программе, ему обязательно надо присвоить адрес какого - либо данного, т.е. проинициализировать, иначе могут быть непредсказуемые результаты. Для доступа к значению переменной, адрес которой хранится в указателе, достаточно в соответствующем операторе программы записать имя указателя с символом "*" , например:
int *p, *p1; // Объявлены два указателя на ячейку памяти int; int x =12, y=5, m [7 ]; // Объявлены переменные x,y и массив m, // переменные x,y проинициализированы p = &y; // Указателю p присвоен адрес переменной y. Теперь, если написать оператор вывода на экран в виде : cout << "Адрес р " << p << "Значение по этому адресу= " <<*p; ,
то выведется адрес ячейки памяти, где записана переменная y и значение этой переменной (т.е. 5). Используя запись x = *p; ,получаем x=5, т.к. *p = y = 5; . Изменить значение y можно записав: y = 10; // или *p = 10; и выполнив операцию *p= *p+5; // это равносильно операции y = y + 5; т.е. y = 15.
При объявлении указателей, им нужно присваивать начальные значения ( инициализировать ), при этом можно либо присваивать адрес объекта (пере- менной), либо адрес конкретного места памяти (массива), либо число 0 (нуль),например: int *pt = (char *) 0x00147; // Присваивается адрес ячейки int *arrpt = new int [10]; // Определяется начальный адрес размещения // динамического массива сhar *p = 0; // Инициализация нулем Поскольку указатели — это специальные переменные, то в операциях с другим указателями они могут использоваться без символа "*", т.е. без раскрытия ссылки, например:
float *pt1, *pt2 , x=15, m[5]; pt1=& x; pt2= pt1; pt1 = m; // или pt1 = & m[0]; m — это имя массива, которое в // рассматриваетсякак специальный указатель – константа. Приведем иллюстрационную программу с использованием указателей: // P2_5.CPP — применение указателей # include < iostream. h > void main ( ) { int x = 10; int *px = &x; cout << " x =" << x << endl; cout << "*px =" << *px << endl; x* = 2; // или x = x*2; cout << " Новое значение* px =" << *px << endl; *px += 2; // или *px =*px + 2; cout << " Новое значение* px=, т.е. х=" << x << endl; } Результат выполнения программы: x = 10 *px = 10 Новое значение *px = 20 Новое значение*px, т.е. x = 22 Сам указатель-переменная имеет свой адрес, поэтому будет справедлива следующая запись: int *pt1, *pt2; pt1 = (int*) &pt2; // здесь указателю pt1 присваивается адрес памяти, // где расположена переменная pt2 Это имеет смысл в ситуации, когда : int y,*pt1, *pt2 =&y; pt1 = (int*) & pt2; . Существуют следующие ограничения на использование операции взятия адреса "&" : — нельзя определять адрес константы ( поскольку ей не отводится ячейка памяти), т.е. недопустима запись : vp = &345; — нельзя определять адрес результата арифметического выражения, поэтому следующая запись неверна : vp = & (x + y); .
Для переменных – указателей разрешены операции: — присваивания; — инкремент и декремент; — сложение и вычитание; — сравнение указателей одинакового типа. Например, демонстрационная программа с использованием переменных-указателей может иметь вид:
//P2_6.CPP — использование переменных- указателей # include < iostream . h > void main ( void ) { int near *ptr1 = (int*)100 ; int near *ptr2 = (int*) 200; ptr1++; ptr2 -= 10; cout << "*ptr1=" << *ptr1 << endl; cout << "*ptr2=" << *ptr2 << endl; cout << "*ptr2 - *ptr1=" << *ptr2 -* ptr1 << endl; } Результат выполнения программы : * ptr1 = 102 * ptr2 = 190 * ptr2 - ptr1 = 88 В программе операця ptr1++ увеличит адрес на 2 байта , поскольку данные типа int занимают 2 байта .
Популярное: Генезис конфликтологии как науки в древней Греции: Для уяснения предыстории конфликтологии существенное значение имеет обращение к античной... Почему двоичная система счисления так распространена?: Каждая цифра должна быть как-то представлена на физическом носителе... ©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (347)
|
Почему 1285321 студент выбрали МегаОбучалку... Система поиска информации Мобильная версия сайта Удобная навигация Нет шокирующей рекламы |