110 likes | 279 Views
Лекция 5. Адресные типы. Адресные типы. Указатели адрес (размещение в памяти) объекта Массивы последовательность однотипных данных Ссылки альтернативное имя объекта. Указатели.
E N D
Лекция 5 Адресные типы
Адресные типы • Указатели адрес (размещение в памяти) объекта • Массивы последовательность однотипных данных • Ссылки альтернативное имя объекта
Указатели Для каждого типа 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 ; typedefint * pint ; pint m ; // pint эквивалентен int*
Инициализация и взятие адреса Переменная типа «указатель» может быть проинициализирована : • численным значением адреса • адресом существующей переменной (с помощью оператора взятия адреса) Оператор &применяется только к lvalue int n = 7 ; int * pv = 0 ; int * px = NULL ; int n = 7 ; int * pv = &n ; float f = 9 ; float * pg = &f ; // Можно int * pv = &n ; // Нельзя!!! int * pv = &7 ;
Разыменование Чтобы обратиться к переменной, адрес которой хранится в указателе, используют оператор разыменования *. Результатом разыменования является 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 n m pn ppn
Массивы Для каждого типа Tтип T[size] является массивом объектов типа T. Переменная типаT[size]содержит неразрывный набор объек-тов типа T, индексированных от 0 до size-1 Размер массива должен быть константным выражением int n [10]; charpn [12]; float c[1]; void f[20]; int n ; int an[7] ; typedefintaint7[7]; aint7 am ;
Инициализаторы массивов • Массив инициализируется списком значений • Если количество значений меньше размера массива, его остальным элементам присваивается 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};// Ошибка
Строки и строковые литералы • Строковым литералом является последовательность символов, заключенная в кавычки. • Тип строкового литерала – массив с достаточным количеством символов (с учетом концевого нуля) • Могут быть инициализатором массива • Используют модификатор L в том же смысле, что и символьные литералы. "Hello world" sizeof("Hello“) == 6 ; // const char[6]; char c[] = "Hello" ; char d[] = {'H', 'e', 'l', 'l', 'o', 0 }; "Hello" ; // const char[6] L"Hello" ; // const wchar_t[6]
Строковые литералы • Могут быть присвоены переменной типа char* (Не рекомендуется) • Память под строковые литералы выделяется статически • Могут быть заданы в несколько строк char s1[] = "Hello world";// Ошибка char s2[] = "Hello\nworld“ ; // Строка с переносом char s3[] = "Hello “ "World“ ; // Многострочное задание
Арифметика указателей • Размер указателя = разрядность системы sizeof(T*)=sizeof(size_t) • Разность указателей sizeof(T*-T*)=sizeof(diff_ptr) • Сумма/разность указателя и интегрального типа • Операции сравнения int * pn pn+1
Двойственность указателей и массивов • Имя массива может быть использовано как указатель на первый элемент массива 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]