Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Konspekt_S.doc
Скачиваний:
23
Добавлен:
09.02.2015
Размер:
1.15 Mб
Скачать

Преобразования типов данных

Рассмотрим пример:

Определены переменные

int a = 5;

double b = 7.6;

В программе необходимо подсчитать их сумму a + b.

Внутреннее (машинное) представление типа intи типаdoubleсущественно различаются. Существенно различаются и процедуры сложения целых значений и процедуры сложения вещественных значений. Как же тогда сложить целое и вещественное? Выход – преобразовать оба значения к одному и тому же типу данных, а затем выполнить соответствующую операцию. Но если преобразовать значение переменнойbк целому типу данных (отбросить дробную часть или округлить до ближайшего целого) результат будет равен либо 12, либо 13, то есть произошла потеря точности. А вот если сначала преобразовать значениеaк типуdoubleи сложить их как вещественные значения, тогда точность потеряна не будет (результат будет равен 12.6 и будет вещественного типа). На самом деле так и происходит.

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

В языке C++ различаютнеявное(автоматическое) иявное преобразование типов данных.

Неявное преобразование типов данных при выполнении операций, подобной рассмотренной выше (и в ряде других случаев), выполняется компилятором по определенным правилам автоматически. В чем же состоят эти правила?

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

  1. Все данные типов charиshort intпреобразуются к типуint.

  2. Если хотя бы один из операндов имеет тип double, то и другой операнд преобразуется к типуdouble(если он другого типа); результат вычисления имеет типdouble.

  3. Если хотя бы один из операндов имеет тип float, то и другой операнд преобразуется к типуfloat(если он другого типа); результат вычисления имеет типfloat.

  4. Если хотя бы один операнд имеет тип long, то и другой операнд преобразуется к типуlong(если он другого типа); результат имеет типlong.

  5. Если хотя бы один из операндов имеет тип unsigned, то и другой операнд преобразуется к типуunsigned(если его тип неunsigned); результат имеет типunsigned.

Если ни один из случаев 1-5 не имеет места, то оба операнда должны иметь тип int; такой же тип будет и у результата.

Следует отметить, что компиляторы языка C++ достаточно свободно выполняют подобные преобразования, что может в ряде случаев привести к неожиданным результатам. Например:

#include <iostream>

using namespace std;

int main()

{

unsigned a = 5;

int b = 10;

cout << a << " - " << b << " = " << a - b << endl;

system("Pause");

return 0;

}

Результат работы программы: 5 – 10 = 4294967291

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

Для исправления ошибки в работе предыдущей программы можно, например, изменить вычисление выражения ab следующим образом:(int) abилиint(a) – b. В этом случае мы получим правильный результат:5 – 10 = -5.

Здесь было использовано явное преобразование типов данных.

Явное преобразование типов данных осуществляется с помощью соответствующей операции преобразования типов данных, которая имеет один из двух следующих форматов:

(<тип данных>) <выражение>или<тип данных> (<выражение>)

Например:

(int) 3.14 int (3.14)

(double) a или double (a)

(long) (a + 1e5f) long (a + 1e5f)

Подобные преобразования имеют своим исходом три ситуации:

  • преобразование без потерь;

  • с потерей точности;

  • с потерей данных.

Преобразование происходит без потерь, если преобразуемое значение принадлежит множеству значений типа, к которому осуществляется преобразование. Например:

short a = 100;

cout << (int) a << endl;// На экран выведено100

cout << (char) a << endl;// Выведена букваd (ее десятичный эквивалент - 100)

cout << (float) a << endl;// На экран выведено100

cout << (double) a << endl;// На экран выведено100

float b = 3.14f;

cout << (double) b << endl; // На экран выведено 3.14

double d = 3.14;

cout << (float) d << endl; // На экран выведено 3.14

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

double d = 3.74;

cout << (int) d << endl;// На экран выведено3

А вот попытки преобразования значений выходящих за пределы диапазона типа данных, к которому осуществляется преобразование, приводят к полному искажению данных. Например:

int a = -100;

cout << (unsigned) a << endl; // На экран выведено 4294967196

int a = 50000;

cout << (short) a << endl; // На экран выведено -15536

float b = 3e+9f;

cout << (int) b << endl; // На экран выведено -2147483648

double d = 3e+9;

cout << (int) d << endl; // На экран выведено -2147483648

double d = 3e+40;

cout << (float) d << endl; // На экран выведено 1.#INF - переполнение

double d = -3e+40;

cout << (float) d << endl; // На экран выведено -1.#INF - переполнение

Рассмотренная операция преобразования типов перешла в C++ изC. ВC++ имеются свои операции преобразования типов данных. Например, рассмотренные выше преобразования вC++ можно было бы выполнить с помощью операцииstatic_cast, имеющей следующий формат:

static_cast <тип данных> (выражение)

Например:

static_cast <double> (a + 2e+40f)

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

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

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