В параграфе операции кратко уже описывалась операция преобразования типа. В этом параграфе операция преобразования типа будет разобрана полностью с соответствующими примерами.
Операция явного преобразования типа в языке Си++ имеет две различные формы. Каноническую, унаследованную от языка С, и функциональную, которые имеют следующий формат:
(type) операнд // каноническая форма
type (операнд) // функциональная форма
где type – основной, составной или определенный пользователем тип данных; операнд – константа, переменная или структурированный объект произвольного типа. Результатом выполнения операции явного преобразования типа является создание неименованного объекта типа type, который инициализируется значением операнда.
При явном преобразовании типа может происходить или не происходить потеря точности, хотя компилятор всегда старается по возможности преобразовать число с максимальной точностью. Всё зависит от того, из какого в какой тип происходит преобразование. Так, переменная типа long имеет 10 значащих цифр, а переменная типа float - только семь. Поэтому при преобразовании типа из long в float компилятор вынужден отбросить младшие разряды числа, сохранив при этом порядок и старшие разряды числа.
Примеры:
long k = 123456789; /* Определение переменной k (задаётся её тип – long и значение) */1234567e+2
float g = float(k); /* В соответствии с таблицей приоритетов операций сначала выполняется операция преобразования типа, т.е. float(k). Результатом выполнения этой операции является создание неименованной переменной типа float, которая инициализируется в данном случае с потерей точности значением переменной k. При этом ни тип, ни значение переменной k не изменяются. Далее определяется переменная g типа float, которая инициализируется значением неименованной переменной. Область существования неименованной переменной – данная строка программы. При переходе к следующей строке программы неименованная переменная уничтожается.*/
cout<<”\n float(k) = “<<float(k); /*Оператор выведет на экран (float(k) = 1.234567e+08) результат операции преобразования типа, на примере которого можно видеть, что младшие разряды отброшены. */
double pi = 3.14159;
cout<<”\n int(pi) = “<<int(pi); /*Результатом выполнения этих строк программы будет вывод строки программы int(pi) = 3 на экран монитора. Дробная часть числа отброшена. */
cout<<”\n double(k) = “<<double(k); /* Результат (double(k) = 1.23456789е+08) потеря точности при преобразовании типа не происходит, так как число double имеет 15 значащих цифр. */
Кроме явного преобразования типа для арифметических операций и арифметических типов данных в языке Си++ определена операция неявного преобразования типа. Суть её состоит в том, что если в арифметической операции участвуют два операнда разного типа, то происходит неявное преобразование типа одного операнда к типу другого и только после этого происходит выполнение операции. Из двух возможных типов операндов компилятор всегда выбирает наиболее точный (в соответствии со схемой, изображенной на рис. 3.2) и преобразует к нему один из операторов. Этот же тип является типом результата операции.

Рис. 3.2. Схема арифметических преобразований типов, гарантирующих сохранение значимости
Из рис. 3.2 видно, что если в арифметической операции участвуют два операнда, например, типа int и double, то операнд типа int будет неявно преобразован к типу double, так как double точнее int, затем выполнится арифметическая операция, результат которой будет иметь тип double. Пример:
int f = 2;
double e = 2.71;
f = e * f; /*f неявно преобразуется к типу double; выполняется операция умножения; результат операции равен 5.42 и имеет тип double. */
f = 1- e; /* константа единица имеет тип int, который по умолчанию преобразуется к типу double, выполняется операция вычитания; результат операции равен -1.71 типа double.*/
При записи арифметических выражений необходимо помнить, что правило неявного преобразования типа и все рассуждения, связанные с сохранением точности, относятся не ко всему выражению в целом, а к отдельно взятым операциям. Так, например:
int a =1, b = 2;
double f = 1;
f = a/b*f+a*f/b;
cout <<”\ n f = “<< f; /* На экран монитора выводится результат f = 0.5, хотя логичнее было бы предположить, что результат должен быть равен единице. */
Полученный результат объясняется тем, что операции в выражении выполняются последовательно друг за другом в строгом соответствии с их рангом и направлением ассоциативности. Следовательно, первой выполнится операция (a/b). Оба операнда у неё имеют тип int, поэтому неявного преобразования типа не происходит; результатом операции является неименованная переменная типа int, значение которой равно нулю (дробная часть при делении целых чисел отбрасывается). Второй выполняется операция умножения неименованной переменной типа int на переменную f типа double, в результате умножения нуля типа int на единицу типа double получаем ноль типа double. Далее выполняется операция (а*f), в результате получаем единицу типа double. Единица типа double делится на переменную b типа int, получаем 0.5 типа double. Ноль типа double складывается с 0 типа double, получаем 0.5 типа double. Результат выполнения выражения a/b*f+a*f/b равен 0.5 типа double.
Таким образом, потеря точности произошла во время выполнения одной из операций (в данном случае a/b) и значение всего выражения стало не тем, которое можно было бы ожидать. Приведём ещё несколько примеров
Short int a = 10000, b = 5;
double c = 1.;
c = a * b / c; /* потеря точности происходит при выполнении операции a*b. Так как оба операнда имеют тип int, то результат тоже будет иметь тип int. Но в результате выполнения операции a*b получается значение 50000, которое выходит за допустимый диапазон значений переменных типа int. Поэтому значение выражения a*b/c будет непредсказуемо. */
unsigned int a = 5, b=70;
double k = 1;
k = k *(a - b);. /*Результат выполнения операции (a-b) имеет тип unsigned int, а число –65 выходит за допустимый диапазон значений типа unsigned int, поэтому значение выражения k*(a-b) будет непредсказуемо. */
k = 1/2* b; /*Значение выражения 1/2*b равно нулю. Так как первой выполняется операция деления, оба операнда - целые константы. Следовательно, результат выполнения операции тоже будет иметь тип int и будет равен нулю (при делении целых операндов дробная часть отбрасывается). Чтобы получить правильный результат, нужно сделать хотя бы одну константу константой вещественного типа. Для этого рядом с ней нужно поставить точку 1./2*b. */
Таким образом, при вычислении арифметических выражений может быть потеряна точность при выполнении какой-то операции или из-за отбрасывания дробной часть, или из-за переполнения разрядной сетки машины. Чтобы этого не происходило, лучше в выражении использовать только вещественные типы данных.
Неявное преобразование типа над арифметическими типами данных происходит также при выполнении операции присваивания (=). Операция заключается в том, что если арифметический тип данных, стоящий справа от операции (=), не совпадает с типом левого арифметического операнда, то происходит неявное преобразование типа правого операнда к типу левого в независимости от того, какой из типов точнее и теряется при выполнении этой операции точность или нет. Пример:
int k;
double pi= 3.1415;
k = pi; /*Создаётся неименованная переменная типа int, которая инициализируется значением переменной pi; при этом происходит потеря точности. Ни тип, ни значение переменной pi не изменяются. После этого значение неименованной переменной присваивается переменной k.*/
Таким образом, правило преобразования типа данных по умолчанию над арифметическими типами данных для арифметических операций и операции присваивания отличаются друг от друга.
Проектные задания
1. Набрать и отладить прогграмму 1.1. Модифицировать программу так, чтобы по центру экрана выводилось Фамилия И.О. учащегося.
2. Переведите в двоичный и шестнадцатеричный вид год Вашего дня рождения. Для проверки полученного результата осуществите обратный перевод с двоичной и шестнадцатеричной системы в десятичную.
3. Запишите свою фамилию, используя управляющие символы ESC-последовательности и ASCII коды таблицы 1251 – MS Windows.
4. В выражении (3+4>5 && 3+5 > 4 && 4+5>3) содержится 8 операций. Пометьте цифрами, в какой последовательности будут выполняться эти 8 операций. Найдите вручную, чему равно значение выражения (3+4>(5 && 3)+5 > 4 && 4+5>3). Объясните почему
5. Приведите примеры явного и неявного преобразования типов данных при выполнении арифметических операций и операции присваивания.
6. Напишите функцию, вычисляющую модуль, и функцию, вычисляющую аргумент комплексного числа.
7. Набрать и отладить программу 2.7, выполнить её в пошаговом режиме. Выписать значения фактических параметров при вызове функций
8. Набрать и отладить программу 2.8. Модифицировать её так, чтобы найти значения sin(π/4), cos(π/4) и tg(π/4)
9. Набрать и отладить программу 3.1, выполнить её в пошаговом режиме. Рассказать какой тип, класс памяти, продолжительность существования, сфера действия имени, видимость и тип компоновки имеют все переменные в данной программе.
10. Набрать и отладить программу 3.2. Убедится в том, какие значения принимают глобальные переменные с внутренней и внешним типом компоновки.
Тесты рубежного контроля
1. Какие типы данных, из перечисленных ниже, являются вещественными?
a) double
b) Int
c) Long
2. Какие типы данных из перечисленных ниже являются целыми?
a) Long
b) Float
c) Long double
3. сколько байтов занимает тип long
a) 1
b) 4
c) 8
4. В каком диапазоне могут изменяться значения типа char?
a) 0…255
b) -128…127
5. Укажите, какая из предложенных констант является константой типа double
a) 1
b) 1.L
c) 1.
6. Укажите, какая из предложенных констант, является константой типа int
a) 2.
b) 2L
c) 2
7. Укажите, какая из предложенных констант, является строковой.
a) ‘A’
b) “A”
8. Какой из управляющих символов является символом перевода каретки на новую строку
a) \t
b) \n
c) \r
9. После компиляции C программы компилятор создаёт файлы с расширением:
a) *.exe
b) *.lib
c) *.obj
10. Выберите, какой из идентификаторов записан неверно
a) 1Array
b) temp
c) obj
11. Унарная операция – это операция с
a) двумя операндами
b) тремя операндами
c) одним операндом
12. Какой из предложенных ниже символов не является операцией в языке Си++
a) ()
b),
c) #
13. Чему равно значение выражения 3&7
a) 1
b) 3
c) 7
14. Чему равно значение выражения 3&&7
a) 1
b) 3
c) 7
15. Чему равно значение выражения 3|7
a) 1
b) 3
c) 7
16. Чему равно значение выражения 3||7
a) 1
b) 3
c) 7
17. Чему равно значение выражения 15%8
a) 1
b) 3
c) 7
18. Чему равно значение переменной k = 1; k*=3+4;
a) 1
b) 3
c) 7
19. В какой последовательности выполняются операции в следующем выражении -1+2*3
a) - + *
b) - +
c) + -
d) - * +
20. Что такое описание функции
a) тип имя_функции(список формальных параметров);
b) тип имя_функции(список формальных параметров){тело функции}
c) имя_функции(список фактических параметров);
21. Что такое определение функции
a) тип имя_функции(список формальных параметров);
b) тип имя_функции(список формальных параметров){тело функции}
c) имя_функции(список фактических параметров);
22. Что такое вызов функции
a) тип имя_функции(список формальных параметров);
b) тип имя_функции(список формальных параметров){тело функции}
c) имя_функции(список фактических параметров);
23. Сколько в вызове функции fun(fun1(3)+fun2(5), 2+fun4()); фактических параметров
a) 2
b) 3
c) 4
24. Поясните, с помощью какого оператора функция возвращает значение в точку вызова.
a) Goto
b) Break
c) return
25. Какой тип возвращаемого в точку вызова значения функции int fun(double, long)?
a) int
b) double
c) long
26. Чем является запись extern int k;
a) определениеv переменной k
b) описанием переменной k
27. Функция с определением void fun(){static int k=0; k++;} вызывается три раза. Чему равно значение переменной k после третьего вызова
a) 1
b) 2
c) 3
28. Функция с определением void fun(){int k(0); k++;} вызывается три раза. Чему равно значение переменной k после третьего вызова
a) 1
b) 2
c) 3
29. Какие переменные называются локальными?
a) переменные, определённые в блоке или в списке формальных параметров функции.
b) переменные, определённые за пределами блока
30., Какие переменные называются глобальными?
a) переменные, определённые в блоке или в списке формальных параметров функции.
b) переменные, определённые за пределами блока
31. Где содержатся описания библиотечных функций
a) в библиотеке
b) в заголовочном файле
c) в настройках проекта
32. Какое значение будет иметь переменная k после выполнения следующих двух строк программы float k = 3.14; long g = long(k);
a) 3
b) 3.14
33. Какое типу будет пренадлежать переменная k после выполнения следующих двух строк программы float k = 3.14; long g = long(k);
a) long
b) float
34. Чему равно значение переменной f после выполнения следующих трёх строк программы int a =1, b = 2; double f = 1; f = a/b*f+a*f/b;
a) 1
b) 0.5
c) 2
35. Чему равно значение переменной f после выполнения следующей строк программы double f = 1/2 * 2;
a) 0
b) 1
c) 2
Таблица правильных ответов
| № Вопроса | Правильный ответ | № Вопроса | Правильный ответ |
| 1 | a | 19 | d |
| 2 | a | 20 | a |
| 3 | b | 21 | b |
| 4 | b | 22 | c |
| 5 | c | 23 | a |
| 6 | c | 24 | c |
| 7 | b | 25 | a |
| 8 | b | 26 | b |
| 9 | c | 27 | c |
| 10 | a | 28 | a |
| 11 | c | 29 | a |
| 12 | c | 30 | b |
| 13 | b | 31 | b |
| 14 | a | 32 | b |
| 15 | c | 33 | b |
| 16 | a | 34 | b |
| 17 | c | 35 | a |
| 18 | c |
Квалиметрическая оценка
В зависимости от времени и цели проведения тестирования количество вопросов в тесте может менятся. Поэтому, чтобы можно было оценить успеваемость тестируемых студентов, предлагается следующая шкала. Если количество правильных ответов лежит в диапазоне
от 85 до 100% - это отлично;
от 70 до 84% - это хорошо;
от 55 до 69% - это удовлетворительно;
менее 55% - это не удовлетворительно.
Список литературы
1. В.В. Подбельский Язык Си++: Учебное пособие. - 5-е изд. - М.: Финансы и статистика, 2000. - 560с. ил.
2. Ален И. Голуб. Си и Си++ правила программирования. - М.: БИНОМ, 1996. - 272с.
3. Бьерн Страуструп Язык программирования Си++. 3-е изд. /Пер. с англ. - СПб.; М.: «Невский диалект» - «Издательство БИНОМ», 1999. - 991с. ил.
МОДУЛЬ 2
Основной целью данного модуля является изучение операторов языка Си++, операций с указателями и массивами данных.
4. ОПЕРАТОРЫ ЯЗЫКА Си++
Операторы алгоритмических языков программирования являются средством, с помощью которого программист записывает последовательность действий, которую необходимо выполнить вычислительной машине для решения какой-то конкретной задачи. В информатике такую последовательность действий называют алгоритмом. Алгоритм обычно может быть представлен или в графической форме, или в виде текстового описания. Знание алгоритмов решения, хотя бы типовых задач, обычно встречающихся в профессиональной области обучаемого, является залогом успеха его успеваемости по информатике.
Практически все алгоритмические языки с незначительными вариациями имеют один и то же набор операторов. Не стал исключением и язык Си++, который почти без изменений унаследовал от языка Си их конструкции.






