Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебник 357.docx
Скачиваний:
27
Добавлен:
30.04.2022
Размер:
1.75 Mб
Скачать

11.3 Примеры работы с указателями

Пример 1. Реализация операции присваивания указателей

intx = 1, y, z = 3;

int *p, *q;

p = &x;

printf("%d\n", *p); // на печать 1

y = *p;

printf("%d\n", y); // на печать 1

*p = 0;

printf("%d %d\n", x, y); // на печать 0 1

q = &z;

printf("%d\n", *q); // на печать3

p = q;

*p = 4;

printf("%d\n", z); // на печать4

printf("%p %p\n", p, q); // на печать 4 4

Пример 2. Реализация операции преобразования типов

Если указатели ссылаются на различные типы, то при присваивании значения одного указателя другому, необходимо использовать преобразование типов. Без преобразования можно присваивать любому указателю указатель void *.

int main()

{

float PI=3.14159,*p1;

double *p2;

//В переменную p1 записываем адрес PI

p1=Π

//указателю на double присваиваем значение, которое ссылается на тип float.

p2=(double *)p1;

printf("По адресу p1=%p хранится *p1=%g\n",p1,*p1);

printf("По адресу p2=%p хранится *p2=%e\n",p2,*p2);

}

По адресу p1=0012FF7C хранится *p1=3.14159

По адресу p2=0012FF7C хранится *p2=2.642140e-308

В указателях p1 и p2 хранится один и тот же адрес, но значения, на которые они ссылаются, оказываются разными. Это связано с тем, что указатель типа *float адресует 4 байта, а указатель*double – 8 байт. После присваивания p2=(double *)p1; при обращении к *p2 происходит следующее: к переменной, хранящейся по адресу p1, дописывается еще 4 байта из памяти и в результате значение *p2 не совпадает со значением *p1.

Преобразование типов в сторону уменьшения размера отводимой памяти также приведет к некорректным результатам. Так приведенная ниже программа выделит младший байт шестнадцатеричного числа 0x8e41.

int main()

{

int i, *ptr;

i = 0x8e41;

ptr = &i;

printf("%х\n", *ptr); // на печать 0x8e41

printf("%х\n", *((char *)ptr)); //на печать 0x41

}

Пример 3. Сравнение указателей

В общем случае сравнение двух указателей одной из операций отношения имеет смысл, если оба адресуют общий для них объект.

int main()

{

inta, b;

int *p1, *p2, *p3;

p1=&a; p2=&b;p3=p1;

if(p1!=p2) printf (“Указатели p1:%p и p2:%p неравны”, p1, p2);

if(p1==p3) printf (“Указатели равны”);

}

11.4 Практические задания

1. Определите объем памяти, выделяемой под указатель на переменные типа char, int, double.

Под сам указатель (там, где хранится адрес) также должна быть выделена память. Объем этой памяти можно узнать с помощью функции sizeof():

int *pi;

float *pf;

printf("%lu\n", sizeof(pi));

printf("%lu\n", sizeof(pf));

Под указатели всех типов выделяется одинаковый объем памяти, т. к. размер адреса не зависит от типа, а зависит от вычислительной системы. Однако по типу данных определяется, сколько ячеек памяти занимает значение, на которое ссылается указатель, и через сколько ячеек начнется следующее значение.

2. Проанализируйте приведенный ниже код. Объясните результат.

int main()

{

float PI=3.14159,*p1,*p2;

p1=p2=Π

printf("Поадресуp1=%pхранится *p1=%g\n",p1,*p1);

printf("По адресу p2=%p хранится *p2=%g\n",p2,*p2);

}

! Обратите внимание на спецификатор формата %p. Он используется для вывода значений указателей в функции printf. Но поскольку указатель – это адрес, т.е. целое положительное число, то в зависимости от ситуации можно использовать любые спецификаторы целочисленных переменных. Для наглядности результатов используйте %x– для вывода шестнадцатеричном коде.

3. Выполните приведенный ниже код и определите, на сколько увеличится значение, на которое указывает ра. Полученные результаты поясните.

int *pа, x;

pа = &x;

pа++;

4. Выполните приведенный ниже код, выведя на печать все задействованные переменные до и после выполнения арифметических операций. Поясните, что получается в результате операции инкрементирования и декрементирования.

double *p1;

float *p2;

char *i;

p1++;

p2--;

i++;

Перед выполнением операций обязательно выполните инициализацию указателей через описание переменных (см. первый способ инициализации).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]