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

Операция преобразования типов

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

// program-1

# include<stdio.h>

# include<conio.h>

void main ()

{ unsigned long L = 0x12345678L;

char *cp = (char *)&L;

int *ip = (int *)&L;

long *lp = (long *)&L;

void *vp;

int x = 25;

float y = 1.2345;

clrscr();

printf ("&L = %x \n", &L);

printf ("cp = %x *cp = %x \n", cp, (int)*cp);

printf ("ip = %x *ip = %x \n", ip, (int)*ip);

printf ("lp = %x *lp = %lx \n", cp, (long)*lp);

vp = &x;

printf (" *vp = %d \n", * (int*)vp);

vp = &y;

printf (" *vp = %7.4f \n", * (float*)vp);

getch();

}

Результат выполнения этой программы (в каждой конкретной реализации транслятора вместо fff2 возможно другое значение адреса):

&L = fff2 cp = fff2 *cp = 78 ip = fff2 *ip = 5678 lp = fff2 lp = 12345678 *vp = 25 * vp = 1.2345

В программе используются четыре указателя cp, ip, lp, vp. Все они разных типов, а первые три настраиваются на участок памяти, занятый переменнойLтипаunsigned long. Спрашивается можно ли было инициироватьоператоромchar *cp = &L;? Нет, этот оператор вызовет ошибку при трансляции. Дело в том, что cp – это указатель типаchar *,а операция&Lформирует адрес переменнойL, т. е. формирует указатель, значение которого равно адресу участка памяти, занимаемого переменнойL. Но какого типа это будет указатель? ПосколькуL– переменная типаunsigned long, то этот указатель будет типаunsigned long *,а это значит, что в оператореchar *cp = &L;делается попытка присвоить указателю типаchar *значение указателя типаunsigned long *.А это недопустимо! Поэтому в данном случае используется явное преобразование типов и оператор записывается в следующем виде :

char *cp = (char *)&L; В этом операторе операция (char *) приводит указатель &L к типу char *. Аналогично написаны операторы инициации переменных ip, lp. Итак, операторы

char *cp = (char *)&L;

int *ip = (int *)&L;

long *lp = (long *)&L;

настраивают три указателя разных типов на один и тот же участок памяти. Именно поэтому при печати мы видим, что все они имеют одно и то же значение fff2 – адрес размещения переменной L (см. рис. 2).

Печать же содержимого полей (*cp, *ip, *lp), на которые указывают cp, ip, lp, происходит в соответствии с типом указателей, который определяет количество байтов, рассматриваемых при выводе информации (еще раз см. рис.2).

Явное преобразование типов при работе с разными указателями в одном выражении необходимо для всех указателей кроме указателей типа void *. При использовании указателей типа void * операция приведения типа выполняется по умолчанию (указателю типа могу присваиваться значения любых указателей). Указатель типа void * отличается от других указателей отсутствием сведений о размере соответствующего ему участка памяти. Указатель типа void * создан “на все случаи жизни”, но для его применения всегда следует использовать приведение типов. Возможность “связывания” указателя void * с объектами разных типов демонстрируется в программе с помощью переменной vp. Сначала vp настраиваем на переменную х (оператор vp = &x;). Но при этом указатель vp “не знает”, на какого типа поле он указывает. Поэтому при выводе информации (оператор printf (" *vp = %d \n", * (int*)vp); ) выводимая информация указывается в виде * (int*)vp. Разберем более подробно это выражение. В нем vp – это указатель типа void *, (int*)vp – это уже указатель типа (int*), а * (int*)vp – это уже содержимое поля, на которое настроен указатель типа int*. Аналогично операторами

vp = &y;

printf (" *vp = %7.4f \n", * (float*)vp);

переменная vpнастраивается на область, выделенную дляу(операторvp = &y;), а далее операторомprintfвыводится на экран значение этой области в соответствии с форматом%7.4f.

Соседние файлы в папке attachments_05-09-2012_18-55-54