Лекция 4. Указатели ####################################################################################### Знакомство с указателями =========================================================== Понятие указателя ----------------------------------------------------------- Адресация `````````````````````````````````````````````````````````` .. admonition:: Способы адресации * прямая * косвенная *Прямой доступ* .. code-block:: c int count=154; count++; printf("Address: %x\n",&count); Понятие указателя `````````````````````````````````````````````````````````` *Косвенный доступ* .. code-block:: c int count=154; int*p=&count; (*p)++; printf("Address: %x\n",p); **p** - переменная-указатель, используемая для хранения адреса переменной **count**. Указатели на указатели `````````````````````````````````````````````````````````` *Косвенный доступ второго порядка* .. code-block:: c int count=154; int*p=&count; int**pp=&p; * **p** - указатель на тип **int**. * **pp** - указатель на указатель на тип **int**. * ***pp**- доступ к значению **р** * ****pp** – доступ к значению **count** Применение указателей `````````````````````````````````````````````````````````` .. admonition:: Где применяются указатели? * передача параметров в функцию; * манипуляции адресами; * повышение эффективности кода; * организация динамических массивов; * формирование связей между объектами; Особенности работы с указателями `````````````````````````````````````````````````````````` *Особенности:* * указатель всегда объявляется на определенный тип; * размер указателя определяется разрядностью ОС; * при работе с разнотипными указателями необходимо использовать явное преобразование типа; *Можно объявить указатель на:* * обычную скалярную переменную; * массив; * функцию; * указатель. Объявление и инициализация указателей `````````````````````````````````````````````````````````` *Объявление и присваивание* .. code-block:: c int val1=0; char ch='#'; double pi=3.14159265358; int*p1; char* p2; double*p3; p1=&val1; p2=&ch; p3=π *Объявление и инициализация* .. code-block:: c int val1=0; char ch='#'; double pi=3.14159265358; int *p1 =&val1; char* p2 =&ch; double *p3 =π Второй вариант более безопасен, поскольку указатели не остаются без значений. Пример работы с указателями (1) `````````````````````````````````````````````````````````` Что будет выведено на экран? .. code-block:: c int a=10,b=20; int * pa=&a; int * pb=&b; int *temp; printf("A=%d, B=%d\n",*pa,*pb); printf("A=%d, B=%d\n",a,b); temp=pa; pa=pb; pb=temp; printf("A=%d, B=%d\n",*pa,*pb); printf("A=%d, B=%d\n",a,b); Пример работы с указателями (2) `````````````````````````````````````````````````````````` Что будет выведено на экран? .. code-block:: c int a=10,b=20,temp; int * pa=&a; int * pb=&b; printf("A=%d, B=%d\n",*pa,*pb); printf("A=%d, B=%d\n",a,b); temp=*pa; *pa=*pb; *pb=temp; printf("A=%d, B=%d\n",*pa,*pb); printf("A=%d, B=%d\n",a,b); Адресная арифметика ----------------------------------------------------------- Операции над значениями указателей `````````````````````````````````````````````````````````` Инкремент значения указателя .. code-block:: c int a=0; int * pa=&a; pa++; .. image:: _static/04/ris4.png Адрес увеличивается на размер типа данных в байтах **A2=A1+sizeof(int)** В результате указатель содержит адрес ячейки, вплотную прилегающей к исходной (обращение к ней опасно!) Наиболее естественно использовать указатели с массивами: .. image:: _static/04/ris5.png *Инкремент значения указателя* .. code-block:: c int arr[]={1,2,3,4,5,6,7,8,9,0}; int *p1=&arr[0]; int *p2=&arr[9]; int size=p2-p1; Связывание указателя с началом массива: .. code-block:: c int *p=arr; .. code-block:: c int *p1=&arr[0]; int *p2=p1+2; int size=p2-p1; Указатели и массивы =========================================================== Связывание указателей с массивами ----------------------------------------------------------- Указатели и массивы `````````````````````````````````````````````````````````` *Суммирование элементов массива* .. code-block:: c int arr[N]={1,2,3,4,5, 6,7,8,9,0}; int *p=arr,sum=0; while(p