- •Адреса, указатели, ссылки, массивы Указатели и адреса объектов
- •Объявление и инициализация указателей
- •Инициализация указателей
- •Указатели константы и на константы
- •Типы указателей и операции над ними
- •Указатели на основные типы данных - на арифметические данные и на символьные.
- •Операции над указателями
- •Понятие указателя на указатель
- •Аддитивные операции
- •I. Вычитание
- •Вычитание из указателя целое число:
- •II. Сложение указателя с целым значением
- •Объявление ссылки
- •Инициализация ссылок не обязательна:
- •Массивы
- •Форма объявления одномерного массива (вектора) type имя массива [k];
- •Type имя массива [ k 1] [ k2] …[kn];
- •Внутреннее представление массивов в оперативной памяти
- •Инициализация числовых и символьных массивов.
- •Инициализации символьных массивов
- •Массивы и указатели
- •Указатели и строки
- •Ввод/вывод элементов массивов Ввод/вывод числовых массивов
- •Ввод/вывод символьных массивов
- •Создание динамических массивов.
- •Имя указателя [индекс элемента]
- •Массивы указателей
- •Создание двумерного динамического массива с помощью динамического массива указателей.
- •Указатель на массив. Многомерные массивы динамической памяти.
- •Определение типа массива
- •Определение типа указателя на массив
Типы указателей и операции над ними
Типы указателей могут быть стандартными – указатели на объекты основных типов и производными:
указателями на массивы,
указателями на указатели,
указателями на функции,
указателями на константы,
на структуры,
на объединения,
на объекты классов
и на данные, типов определенных пользователем с помощью спецификатора typedef.
Указатели на основные типы данных - на арифметические данные и на символьные.
Пример работы с указателем на данные арифметического типа int:
int n = 6, *pn = &n;
cout<<pn<<'\t'<< *pn; //будет выведено: 0x01E10FFC 6
//адрес значение
Пример работы с указателем на данные символьного типа char:
char c = 65, *pc= &c;
cout<<pc<<'\t'<< *pc<<'\t'<<&c;
//будет выведено A A A,
то есть при выводе указателя, разыменованного указателя и адреса будет выводиться сам символ с кодом 65 – это прописная латинская буква A
Если мы хотим вывести значение адреса символьной переменной и ее внутренний код надо поступить так:
cout<< (void*)pc<<’\t’<< (int)*pc
//результат: 0x1e76a0c2 65
явно привести указатель к типу void*, а разыменованный указатель к типу int.
Операция - &имя дает однозначный результат – адрес данного объекта.
Результат операции разыменования *имя_указателя – неоднозначен и зависит не только от значения указателя так и от его типа, который указывает размер участка памяти, который будет доступен:
В следующем примере один и тот же адрес переменной рассматривается как значение указателей разных типов:
{. . .
long L = 0x12345678L;
char*ch=(char*)&L;
short*I =(short*)&L;
unsigned long*UN=(unsigned long*)&L;
cout<<hex; //манипулятор вывода в шестнадцатеричном //формате
cout<< (int)*ch<<'\t'<< *I << '\t'<< *UN <<endl;
cout<< (void*)ch<<'\t'<< I <<'\t'<< UN <<endl; …}
Результат фрагмента программы:
0x78 0x5678 0x12345678
0x18efoffc 0x18efoffc 0x18efoffc
В первой строке выведены значения ячеек памяти в шестнадцатеричном формате, во второй строке значения указателей (адресов каждой ячейки).
Значения самих указателей совпали, а значения объектов зависят от размера участка памяти, на который "указывает" соответствующий указатель (1 байт, 2 байта или 4 байта).
Рассмотрим указатель типа void*. Такой указатель может иметь значение – адрес какого-либо объекта программы, однако он не содержит информации о размере этого объекта в памяти, и, следовательно, посредством такого указателя нельзя работать с объектом.
Это можно исправить, используя явное преобразование типа указателя.
Указатель типа void* приводится к любому указателю явным преобразованием типа, например,
void* p; int* ip, i= 10; p = &i; ip = (int*) p;
Любой указатель приводится к типу void* по умолчанию:
int i, j, *b = &i; void* a = &j;
a = b; – допустимо, так как b автоматически приводится к типу void*,
b = a; –недопустимо, надо явно приводить a к типу int*: b= (int*) a;
Операции над указателями
разыменование(*);
преобразование типа явное (только каноническая форма);
присваивание;
взятие адреса (&);
аддитивные операции (сложение и вычитание);
инкремент – автоувеличение (++);
декремент – автоуменьшение (--);
операции отношения.
Первые три операции уже рассмотрены выше. Рассмотрим остальные.
