Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
28
Добавлен:
17.04.2015
Размер:
78.15 Кб
Скачать

14. Присваивание указателей различного типа.

Oперацию присваивания указателей различных типов следует понимать как назначение указателя в левой части на ту же самую область памяти, на которую назначен указатель в правой. Оба указателя после присваивания содержат один и тот же адрес. Но поскольку тип указуемых переменных у них разный, то эта область памяти по правилам интерпретации указателя будет рассматриваться как заполненная переменными либо одного, либо другого типа:

char *p, A[20];

int *q;

long *l;

p = A; q = p; l = p;

В этом примере p - указатель на область байтов, q - на область целых, l - на область длинных целых. Соответственно операции адресной арифметики *(p+i), *(q+i), *(l+i)

адресуют i-ый байт, i-ое целое и i-ое длинное целое от начала области:

+

q +-+

¦---------+

p +-+ +-+ +------->+-------+

¦---------------------->+ A ----+ ¦

+-+ ¦char 0 ¦ ¦int 0

+-------¦ ¦

¦char 1 ¦--¦

+-------¦ ¦int 1

¦char 2* ---------- *(p+2)

+-------¦* -------- *(q+1)

¦char 3 ¦--¦

+-------¦

*(p + 2) = 5; // записать 5 во второй байт области A

*(q + 1) = 7; // записать 7 в первое слово области A

Таким образом, область памяти имеет различную структуру (байтовую, словную и т.д.) в зависимости от того, через какой указатель мы с ней работаем. При этом неважно,

что сама область определена как массив типа char - это имеет отношение только к операциям с использованием идентификатора массива.

Присваивание значения указателя одного типа указателю другого типа сопровождается действием, которое называется в Си "ПРЕОБРАЗОВАНИЕ ТИПА УКАЗАТЕЛЯ". На самом деле это действие не приводит к каким-либо преобразованиями данных (команды транслятором не генерируются). Транслятор просто запо-минает, что тип указуемой переменной изменился и операции адрес-ной арифметики и косвенного обращения нужно выпол-нять с уче-том нового типа указателя. При присваивании происходит автома-тическое неявное преобразование типа указателя, которое в транс-ляторе "классического" Си обычносопровождается предупреждением.

Таким образом, операция присваивания указателя включает в себя:

- присваивание адреса от правого указателя к левому;

- неяное преобразование типа указателя от правого к левому.

22. Явное преобразование типа указателя

Рассмотрим три операции присваивания:

char *p, A[20];

int *q;

p = A;

q = p; *(p + 2) = 5;

*((q = p) + 2) = 5;

*((int *)p + 2) = 5;

// ¦ ¦ +-- тип указателя char* до преобразования

// ¦ +------ явное преобразование указателя

// ¦ на байт в указатель на целое

// +--------- тип указателя int* после преобразования

Все они дают одинаковый результат - записывают целое 5 во второе слово области памяти, определенной как массив байтов (символов) с именем A. Однако, если в первом и втором случае используется промежуточный указатель типа int*, то в последнем случае такой указатель создается как рабочая пере менная, которая получает тип int* и значение пере-мен-ной p. Такая операция называется явным преобразованием типа указателя. В скобках указывается абстрактный тип данных -указатель на требуемый тип (например, int*).