Скачать презентацию
Идет загрузка презентации. Пожалуйста, подождите
Презентация была опубликована 11 лет назад пользователемВалерий Беспалов
1 Лекция 5 Адресные типы
2 Указатели адрес (размещение в памяти) объекта Массивы последовательность однотипных данных Ссылки альтернативное имя объекта
3 Указатели Для каждого типа T тип T* является указателем на тип T, т.е. переменная типа T* содержит адрес переменной типа T int n ; int * pn ; int ** ppn ; char * pc ; float * pf ; void * p ; enum Day { Mon, Tue, Wed }; Day * pday ; int n ; int * pn ; int ** ppn ; char * pc ; float * pf ; void * p ; enum Day { Mon, Tue, Wed }; Day * pday ; int n ; int * pn ; typedef int * pint ; pint m ; // pint эквивалентен int* int n ; int * pn ; typedef int * pint ; pint m ; // pint эквивалентен int*
4 Инициализация и взятие адреса Переменная типа «указатель» может быть проинициализирована : численным значением адреса адресом существующей переменной (с помощью оператора взятия адреса) Оператор & применяется только к lvalue int n = 7 ; int * pv = 0 ; int * px = NULL ; int n = 7 ; int * pv = 0 ; int * px = NULL ; int n = 7 ; int * pv = &n ; int n = 7 ; int * pv = &n ; float f = 9 ; float * pg = &f ; float f = 9 ; float * pg = &f ; // Можно int * pv = &n ; // Можно int * pv = &n ; // Нельзя!!! int * pv = &7 ; // Нельзя!!! int * pv = &7 ;
5 Разыменование Чтобы обратиться к переменной, адрес которой хранится в указателе, используют оператор разыменования *. Результатом разыменования является lvalue int n = 7 ; int m = 8 ; int * pn = &n ; int **ppn = &pn ; n = 9 ; // n = 9 *pn = 12 ; // n = 12 *ppn = &m ;// pn = &m *pn = 7 ; // m = 7 int n = 7 ; int m = 8 ; int * pn = &n ; int **ppn = &pn ; n = 9 ; // n = 9 *pn = 12 ; // n = 12 *ppn = &m ;// pn = &m *pn = 7 ; // m = 7 nm pn ppn
6 Указатель на void Переменные типа void* нельзя разыменовывать Указатель на любой объект можно присвоить переменной типа void* Переменную типа void* можно присвоить другой переменной типа void* Две переменных типа void* можно сравнивать на равенство и неравенство void* можно явно преобразовать в другой тип int n = 0 ; int * pn = &n ; *pn = 7 ; // Можно void * pv = pn ; *pv = 9 ; // Нельзя! float * pf = pv ; float * pq = pn ; float * pr = (float)pv; int n = 0 ; int * pn = &n ; *pn = 7 ; // Можно void * pv = pn ; *pv = 9 ; // Нельзя! float * pf = pv ; float * pq = pn ; float * pr = (float)pv;
7 Массивы Для каждого типа T тип T[size] является массивом объектов типа T. Переменная типа T[size] содержит неразрывный набор объек- тов типа T, индексированных от 0 до size-1 Размер массива должен быть константным выражением int n [10]; char pn [12]; float c[1]; void f[20]; int n [10]; char pn [12]; float c[1]; void f[20]; int n ; int an[7] ; typedef int aint7[7]; aint7 am ; int n ; int an[7] ; typedef int aint7[7]; aint7 am ;
8 Инициализаторы массивов Массив инициализируется списком значений Если количество значений меньше размера массива, его остальным элементам присваивается 0 Указание большего чем размер массива количества значений является ошибкой В случае, если указан список инициализации, можно явно не указывать размер массива Не существует оператора присваивания, идентичной инициализации int n [4] = {1,2,3,4}; int m [6] = {1,2,3,4}; // {1,2,3,4,0,0} int n [4] = {1,2,3,4,5,6}; // Ошибка! int n [] = {1,2,3,4}; // int n[4] = n = {1,2,3,4}; // Ошибка
9 Строки и строковые литералы Строковым литералом является последовательность символов, заключенная в кавычки. Тип строкового литерала – массив с достаточным количеством символов (с учетом концевого нуля) Могут быть инициализатором массива Используют модификатор L в том же смысле, что и символьные литералы. "Hello world" sizeof("Hello) == 6 ; // const char[6]; char c[] = "Hello" ; char d[] = {'H', 'e', 'l', 'l', 'o', 0 }; char c[] = "Hello" ; char d[] = {'H', 'e', 'l', 'l', 'o', 0 }; "Hello" ; // const char[6] L"Hello" ; // const wchar_t[6] "Hello" ; // const char[6] L"Hello" ; // const wchar_t[6]
10 Строковые литералы Могут быть присвоены переменной типа char* (Не рекомендуется) Память под строковые литералы выделяется статически Могут быть заданы в несколько строк char s1[] = "Hello world" ; // Ошибка char s2[] = "Hello\nworld ; // Строка с переносом char s3[] = "Hello "World ; // Многострочное задание char s1[] = "Hello world" ; // Ошибка char s2[] = "Hello\nworld ; // Строка с переносом char s3[] = "Hello "World ; // Многострочное задание
11 Арифметика указателей Размер указателя = разрядность системы sizeof(T*)=sizeof(size_t) Разность указателей sizeof(T*-T*)=sizeof(diff_ptr) Сумма/разность указателя и интегрального типа Операции сравнения int * pnpn+1
12 Двойственность указателей и массивов Имя массива может быть использовано как указатель на первый элемент массива int v[] = {1,2,3,4,5}; v[3] = 7 ; int * p1 = v ; // p1 указывает на v[0] int * p2 = &v[2]; // p2 указывает на v[2] int * p3 = v + 3 ; // p3 указывает на v[3] *(v+1) = 12 ; // v[1] = 12 p1[4] = 15 ; // v[4] = 15 3[p1] = 7 ; // v[3] = 7 // p1[3] eq *(p1+3) eq 3[p1] int v[] = {1,2,3,4,5}; v[3] = 7 ; int * p1 = v ; // p1 указывает на v[0] int * p2 = &v[2]; // p2 указывает на v[2] int * p3 = v + 3 ; // p3 указывает на v[3] *(v+1) = 12 ; // v[1] = 12 p1[4] = 15 ; // v[4] = 15 3[p1] = 7 ; // v[3] = 7 // p1[3] eq *(p1+3) eq 3[p1]
13 Ссылки Являются альтернативным именем объекта Обязательно инициализируются «опорным» (реферальным) объектом, на который они ссылаются. Не могут быть изменены в процессе программы. Любое изменение ссылки применяется к реферальному объекту. int n = 3 ; int & cn = n ; cn = 7 ; // n = 7 ; float & cf ; // Ошибка! int n = 3 ; int & cn = n ; cn = 7 ; // n = 7 ; float & cf ; // Ошибка!
14 Двойственность указателей и ссылок Ссылки, по сути, это неизменяемые указатели с неявным разыменованием. int n = 7 ; int & cn = n ; int * const pn = & n ; cn = 8 ; // n = 8 *pn = 9 ; // n = 9 int n = 7 ; int & cn = n ; int * const pn = & n ; cn = 8 ; // n = 8 *pn = 9 ; // n = 9
15 Модификатор const Означает, что значение переменной данного типа не может изменяться. Применим к массивам ссылкам int n = 7 ; // Изменяемая переменная const int m = 9 ; // Неизменяемая переменная int const q = 8 ; // То же самое const int p ; // Ошибка! Нет инициализатора n = 11 ; // Нормально q = 6 ; // Ошибка! Константный объект int n = 7 ; // Изменяемая переменная const int m = 9 ; // Неизменяемая переменная int const q = 8 ; // То же самое const int p ; // Ошибка! Нет инициализатора n = 11 ; // Нормально q = 6 ; // Ошибка! Константный объект const int v[] = {1,2,3}; // Все эл-ты константны const int u[]; // Ошибка! Нет инициализатора const int &c = n ; // Ссылка на константу int const *d = n ; // Указатель на константу char const & q ; // Ошибка! Нет инициализатора const int v[] = {1,2,3}; // Все эл-ты константны const int u[]; // Ошибка! Нет инициализатора const int &c = n ; // Ссылка на константу int const *d = n ; // Указатель на константу char const & q ; // Ошибка! Нет инициализатора
16 Тонкости константных объектов Указатель или ссылку на константный объект можно инициализировать неконстантным объектом, но не наоборот. На константность самого объекта такая инициализация не влияет. int n = 7 ; // Изменяемая переменная const int m = 9 ; // Неизменяемая переменная const int & ccm = m ; // Можно const int & ccn = n ; // Можно по правилу int & cn = n ; // Можно int & cm = m ; // Ошибка! m - константа cn = 7 ; // Можно ccn = 7 ; // Ошибка! ссn – ссылка на конст. int const * cpn = &n ; // Можно по правилу int const * cpm = &m ; // Можно int * pm = &m ; // Ошибка! m - константа int n = 7 ; // Изменяемая переменная const int m = 9 ; // Неизменяемая переменная const int & ccm = m ; // Можно const int & ccn = n ; // Можно по правилу int & cn = n ; // Можно int & cm = m ; // Ошибка! m - константа cn = 7 ; // Можно ccn = 7 ; // Ошибка! ссn – ссылка на конст. int const * cpn = &n ; // Можно по правилу int const * cpm = &m ; // Можно int * pm = &m ; // Ошибка! m - константа
17 Константные указатели Помимо оператора объявления * есть оператор *const, означающий неизменяемый (константный) указатель. int * p ; // указатель на целое const int * p ; // указатель на константу int const * p ; // указатель на константу int * const p ; // константный указатель int const * const p ; // константный указатель на // константу const int const * const p ; // перебор int * p ; // указатель на целое const int * p ; // указатель на константу int const * p ; // указатель на константу int * const p ; // константный указатель int const * const p ; // константный указатель на // константу const int const * const p ; // перебор
18 Множественные объявления Модификаторы типа действуют на все переменные во множественном определении, операторы определения ( *, *const, & [], () ) только на те переменные, которым принадлежат. int * n = 7, c = 9 ; // * относbтся к объекту // c – типа int int const * const a, b ; // b – типа const int int k, &l = k, *p = &k ; // k - int // l – int & // p – int * int * n = 7, c = 9 ; // * относbтся к объекту // c – типа int int const * const a, b ; // b – типа const int int k, &l = k, *p = &k ; // k - int // l – int & // p – int *
19 Составные типы Многомерный массив int a[2][3] = {{1,2,3},{4,5,6}}; Указатели на указатели int ** p int *const* q Массивы указателей int * m[10] Указатели на массивы int (*pm)[10] Ссылка на указатель int *& p; Указатель на ссылку не бывает!
Еще похожие презентации в нашем архиве:
© 2024 MyShared Inc.
All rights reserved.