![]() Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву ![]() Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Производные типы. Тип указатель: указатели на объекты
Цель работы: изучить тип указатель и соотношения между именами, адресами и значениями переменных, научиться использовать указатели в программных кодах на языке C++.
Теоретические сведения В языке С++ разрешено использование наряду со стандартными типами производные типы, полученные на основе более простых базовых типов. Производные типы можно условно подразделить на две группы: Непосредственно производные типы. Эти типы являются производными от некоторых существующих типов, реализуя типы указателей, ссылки, функции преобразования типов. В группу непосредственно производных типов входят: · массивы; · указатели; · ссылки; · перечисления. Составные производные типы. В группу составных производных типов входят: · классы; · структуры; · объединения.
Переименование типов В некоторых программных кодах бывает удобно вводить новые обозначения имен отдельных используемых типов данных. Задавать новое имя типу можно с помощью ключевого слова typedef. Синтаксис: typedef Тип НовоеИмяТипа[Размерность]; Например: typedef unsigned int UNIT; typedef char Msg[100]; Такое имя можно затем использовать так же, как и стандартное имя типа: UNIT a,b,c;//переменные типа unsigned int Msg str[10];//массив из 10 строк по 100 символов
Рассмотрим тип указатель. Указатели являются специальными объектами в программах на С++. Они предназначены для хранения адресов памяти. Пример: Когда компилятор обрабатывает оператор определения переменной, например, int i=10;, то в памяти выделяется участок памяти в соответствии с типом переменной (int=> 2 байта) и записывает в этот участок указанное значение. Все обращения к этой переменной компилятор заменит на адрес области памяти, в которой хранится эта переменная. Операция &a является операцией взятия адреса ее операнда.
Рис. Адресация в С++
Программист может определить собственные переменные для хранения адресов областей памяти. Такие переменные называются указателями. Указатель – именованный объект, предназначенный для хранения адреса области памяти (объекта, непоименованной области оперативной памяти либо точки входа в функцию). Указатель не является самостоятельным типом, он всегда связан с каким-то другим типом. Указатели делятся на две категории:
· указатели на объекты; · указатели на функции. Эти категории указателей отличаются друг от друга свойствами и правилами манипулирования. Каждый указатель имеет соответствующий тип.
Указатели на объекты В общем случае синтаксис определения указателя на объект: Тип*Описатель При определении указателя специфицируется имя указателя-переменной (в дальнейшем указатель) и тип объекта, на который он ссылается. Тип задает тип объекта, адрес которого будет содержать эта переменная и может соответствовать базовому, пустому (свободному, родовому, то есть типу void), перечислению, структурному типу и типу объединения. Реально указатель на void ни на что не указывает, но обладает способностью указывать на все что угодно после его типизирования каким-либо объектом. Описатель – это идентификатор, определяющий имя объявляемой переменой типа указатель или конструкция, которая организует непосредственно доступ к памяти. Описателю обязательно должна предшествовать звездочка (*). Знак '*' является унарной операцией косвенной адресации, его операнд – указатель, а результат – адрес объекта, на который указывает операнд. Адресация является косвенной, так как обращение к области памяти осуществляется не напрямую по адресу (например, 1А2В), а через объект, которому в памяти соответствует определенный участок. Объем памяти, который выделяется для хранения данных, определяется типом данных и моделью памяти. Для приведенной на рисунке модели памяти адресом переменной типа char с именем ch является 1А2В, адресом переменной типа int с именем date является 1А2C, адресом переменной типа float с именем summa является 1А2E.
Рис. Адресация типов в С++
Примеры определения указателей: int *P; /*указатель Р может содержать адрес объекта типа int*/ float *s; /*указатель s может содержать адрес объекта типа float*/
Синтаксис указателя на объект базового типа: Тип*ИмяУказателя;
где ИмяУказателя – идентификатор.
Например, char *s; //переменная s – указатель на объект типа char double *x; /*переменная х – указатель на объект типа double, вещественного числа с плавающей точкой удвоенной точности*/ int *k, *ff; //k, ff – указатели на объекты целого типа int *p, y; /*р – указатель на объект типа int, y – целочисленная переменная и не является указателем*/ int x, *p; /*х – целочисленная переменная и не является указателем, р – указатель на объект типа int*/
Указатель может быть константой или переменной, а также указывать на константу или переменную. Например: int i;//целая переменная const int ci=1; //целая константа
int *pi; //указатель на целую переменную const int *pci; //указатель на целую константу
int *const cpi; //указатель-константа на целую переменную const int *const cpc; //указатель-константа на целую константу
При объявлении указателя его можно сразу проинициализировать (задать значение): int *pi=&i; //указатель на целую переменную const int *pci=&ci; //указатель на целую константу
int *const cpi=&i; //указатель-константа на целую переменную const int *const cpc=&ci; //указатель-константа на целую константу
Если модификатор const относится к указателю (т.е. находится между именем указателя и *), то он запрещает изменение значения указателя, а если он находится слева от типа (т.е. слева от *), то он запрещает изменение значения, на которое указывает указатель.
Способы инициализации указателя 1. Присваивание указателю адреса области памяти существующего объекта: · int a=5; int *p=&a;
· с помощью проинициализированного указателя int *r=p;
2. Присваивание указателю адреса области памяти в явном виде: char *cp=(char*)0х В800 0000; где 0х В800 0000 – шестнадцатеричная константа, (char*) – операция приведения типа.
3. Присваивание указателю пустого значения: int *N=NULL; или int *N=0; Спецификатор указателя при форматированном выводе Если на экран необходимо вывести адрес, следует применять спецификатор %p. %p – спецификатор указателя. Этот спецификатор формата заставляет функцию printf() выводить на экран адрес, формат которого совместим с типом адресации, принятой в компьютере.
Операции с указателями С указателями можно выполнять следующие операции: · разыменование (*) – получение значения величины, адрес которой хранится в указателе; · взятие адреса (&); · присваивание; · арифметические операции § сложение указателя только с константой, § вычитание: допускается разность указателей и разность указателя и константы, § инкремент (++) увеличивает значение указателя на величину sizeof(тип); § декремент (--) уменьшает значение указателя на величину sizeof(тип); · сравнение; · приведение типов. Пример 1. Указатели различных типов указывают на одно и то же место в памяти. Однако при разыменовании получаются разные результаты. // Выбор данных из памяти с помощью разных указателей // Использование функций приведения типов #include <iostream.h> void main(){ unsigned long L=12345678; char *cp=(char*)&L; int *ip=(int*)&L; long *lp=(long*)&L;
cout <<"\n&L = "<<&L; cout <<"\nL = "<<L; cout <<"\n*cp = "<<*cp; cout <<"\n*ip = "<<*ip; cout <<"\n*lp = "<<*lp; } Пример 2. //Операции над указателями #include <iostream.h> void main(){
int a,c,b; int *ca, *cb; int *sa, *sb, *sc; cout << "a = "; cin >> a; cout << "b = "; cin >> b; c=a+b;
sb=&b;//инициализация указателей через взятие адреса sa=&a; *sc=c;//инициализация указателя через обращение к переменной ca=sa;//инициализация указателей через другой указатель cb=sb; *sa=12;//инициализация указателя через константу
cout << "\n*ca = " << *ca; cout << "\n*sa = " << *sa; cout << "\n*cb = " << *cb; cout << "\n*sb = " << *sb; cout << "\n*sc = " << *sc;
cout << "\nca = " << ca; cout << "\ncb = " << cb; cout << "\nsc = " << sc;
cout << "\na = " << a; cout << "\nb = " << b; cout << "\nc = " << c;
cout << "\n&a = " << &a; cout << "\n&b = " << &b; cout << "\n&c = " << &c;
cout << "\n*&a = " << *&a;
cout << "\n*cb-*ca = " << *cb-*ca; cout << "\n*cb+*ca = " << *cb+*ca; *cb=+2; //сложение с константой cout << "\ncb = " << cb; cb++; //инкремент cout << "\ncb = " << cb; ca--; //декремент cout << "\ncа = " << cа; /*разность указателей - разность их значений, деленная на размер типа в байтах*/ cout << "\ncb-ca = " << cb-ca; } Указатели одного и того же типа можно сравнивать с помощью стандартных операций сравнения. При этом сравниваются значения указателей, а не значения величин, на которые данные указатели ссылаются. Пример 3. #include <iostream.h> void main() { int x=10; int y=10; int *xptr=&x; int *yptr=&y;
//сравниваем указатели if (xptr == yptr) cout << "Указатели равны\n"; else cout << "Указатели неравны\n";
//сравниваем значения, на которое указывает указатель if (*xptr == *yptr) { cout << "Значения равны\n"; } else { cout << "Значения неравны\n";} } В приведенном примере результат первой операции сравнения будет ложным, а второй – истинным, поскольку переменные x и y имеют одно и то же значение. Задания 1. Наберите код программы из Примера 2. Выполните компиляцию и запуск программы. 2. В программе определите и инициализируйте переменную типа double, указатель double * и указатель типа void *. Присвойте указателям адрес переменной. Напечатайте адрес переменной, значения указателей и значения, получаемые при разыменовании указателей. Чтобы продемонстрировать роли и последовательность выполнения унарных операций получения адреса & и разыменования *, выведите на печать значение выражения *&имя_переменной. 3. Определите и инициализируйте переменные разных типов (char, int, double) и один указатель типа void *. Последовательно присваивая указателю адреса переменных разных типов, выведите значения переменных с помощью разыменования указателя.
Домашние задания 1. Наберите коды программ из Примеров 1 и 3. Выполните компиляцию и запуск программ. 2. Определите и инициализируйте переменную типа double. Определите указатели char *, int *, double *, void *, инициализируйте их адресом переменной. Напечатайте значения указателей, их размеры и длины участков памяти, которые связаны с выражениями, разыменовывающими указатели. Лабораторная работа 23
|
||||||||||||||||||||||||||||||||||||||
Последнее изменение этой страницы: 2016-09-13; просмотров: 212; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.220.26.37 (0.065 с.) |