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

Приведение типов

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

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

Операция приведения типа является унарной и имеет вид: (<тип>)<выражение>. В следующем примере использована операция приведения типа целочисленной переменной a к типу double, чтобы результат деления двух целых чисел был вещественным. Значение выражения (double)a будет иметь тип double и будет равно 5.0, а результат деления – 1.66666666667 (это значение и будет присвоено переменной c). В последней строке операция приведения типа в выражении отсутствует и деление является целочисленным, поэтому его результат равен 1 (только целая часть частного) и это значение будет присвоено переменной d, т.е. дробная часть результата будет потеряна несмотря на то, что переменная d имеет тип double. Здесь, кстати, будет иметь место неявное приведение типа – целочисленное значение 1 будет приведено к значению 1.0 типа double.

int a = 5, b = 3; double c, d;

c = (double)a / b; d = a / b;

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

int x = 1; float y;

y = sin(x);

В данном примере x является аргументом функции sin, которая требует параметр типа double, к которому и будет приведено значение этого целочисленного аргумента. Функция возвращает значение типа double, но при его присваивании переменной y типа float опять произойдет неявное приведение типа. В результате вызов функции и интерпретация значений выполняются правильно, но только в том случае, если включен заголовочный файл math.h, иначе приведения типа в обоих случаях не выполнятся и функция будет вызвана неправильно (результат вычислений будет непредсказуем – от неверного значения вычислений до ошибки во время выполнения программы).

При выполнении приведения типов формат представления значения или его интерпретация изменяются в зависимости от того, какими являются исходный и конечный типы. При этом возможны следующие ситуации:

1. Приведение целочисленного значения к беззнаковому:

char

unsigned char

short

unsigned short

int

unsigned

int

long

unsigned

long

Двоичное представление не изменяется, но меняется трактовка знакового разряда числа – он становится просто старшим разрядом двоичного неотрицательного числа. Например, при приведении значения –210 = 1111'1111'1111'11102 (рамкой обозначен знаковый разряд) типа int к типу unsigned int, двоичное представление и его размер не изменятся. Однако, полученное значение будет интерпретироваться как положительное: 1111'1111'1111'11102 = 6553410 (знаковый разряд отсутствует и

старший разряд двоичного представления эквивалентен 215 = 32768, т.е. число равно

1·215 + 1·214 + … + 1·22 + 1·21 + 0·20).

2. Приведение беззнакового значения к целочисленному со знаком:

unsigned char

char

unsigned short

short

unsigned

int

int

unsigned

long

long

Этот процесс является обратным рассмотренному: двоичное представление числа не изменится, но старший разряд будет рассматриваться как знаковый.

3. Приведение целочисленного значения к большему по размеру целому типу:

char

int

 

short

int

 

int

long

и т.п.

Значение расширяется за счет заполнения старших («новых») разрядов двоичного представления числа значением его знакового разряда:

0100'00112 (+6710) → 0000'0000'0100'00112 (+6710)

1011'11012 (–6710) → 1111'1111'1011'11012 (–6710)

4. Приведение целочисленного беззнакового значения к большему по размеру целому беззнаковому типу:

unsigned char

unsigned int

 

unsigned

short

unsigned

int

 

unsigned

int

unsigned

long

и т.п.

Значение расширяется за счет заполнения старших («новых») разрядов двоичного представления числа нулями:

1011'11012 (18910) → 0000'0000'1011'11012 (18910) 0100'00112 (6710) → 0000'0000'0100'00112 (6710)

Очевидно, что дописывание к числу нулей слева не изменяет значение числа, т.к. эти нули являются незначащими.

5. Приведение целочисленного значения к меньшему по размеру целому типу:

long

int

unsigned long

unsigned int

 

int

short

unsigned

int

unsigned

short

 

int

char

unsigned

int

unsigned

char

и т.п.

Значение просто усекается до требуемого количества разрядов за счет отбрасывания старших разрядов двоичного представления числа вне зависимости от того, является число знаковым или беззнаковым и каково значение знакового разряда, если он есть:

0000'0000'0100'00112

(6710)

→ 0100'00112

(6710)

0000'0001'0100'00112

(32310)

→ 0100'00112

(6710)

0000'0000'1011'11012

(18910)

→ 1011'11012

(–6710)

1111'1111'1011'11012

(–6710)

→ 1011'11012

(–6710)

1111'1111'0100'00112 (–18910)

→ 0100'00112

(6710)

6. Приведение целочисленного значения к типу с плавающей точкой:

int

float

 

long

float

 

long

double

 

int

long double

и т.п.

Значение дополняется нулевой дробной частью и нулевым порядком, после чего нормализуется по правилам конечного типа.

7. Приведение значения с плавающей точкой к целочисленному типу:

float

int

 

float

long

 

double

long

 

long double

int

и т.п.

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

требуемого количества разрядов отбрасыванием «лишних» левых разрядов двоичного представления, если полученное целочисленное значение лежит за пределами диапазона значений конечного типа.

8. Приведение значения с плавающей точкой к большему по размеру типу:

float double float long double double long double

В этом случае увеличивается количество двоичных разрядов, отводимых для представления как мантиссы, так и порядка числа. Правые («новые») разряды мантиссы заполняются нулями (нули, дописываемые справа к дробной части являются незначащими), а порядок расширяется по правилам целого числа со знаком.

m

 

 

n

 

m

| 0 0/1 | n

 

 

 

 

 

 

 

9. Приведение значения с плавающей точкой к меньшему по размеру типу:

long

double double

long

double

float

double

float

В этом случае уменьшается количество двоичных разрядов, отводимых для представления как мантиссы, так и порядка числа. Мантисса усекается справа до требуемого количества разрядов, т.е. младшие («лишние») разряды отбрасываются (уменьшается количество значащих разрядов – уменьшается точность числа), а порядок усекается слева по правилам целого числа со знаком.

m |

 

 

 

| n

 

 

X

 

 

 

X

m'

 

 

n'

 

Если порядок числа велик по модулю и не представим конечным типом, то генерируется сообщение об ошибке во время выполнения, а выполнение программы прерывается.