Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 19
Текст из файла (страница 19)
— ().пг) (х / У)7 сопяо1е.иглсеыпе("целочислеииый результат деления х / у: " + 1) Сопво1е.ыглсещпе () 7 // Приведение типа лпг к типу бусе без потери данных. ). = 2557 Ь = (Ьуге) 17 Сопяо1е.игтгещпе(чЬ после присваивания 255: " + Ь + " — без потери дахиых.")7 // Приведение типа лпс к типу бусе с потерей данных. ). 257 7 Ь " (Ьусе) 17 Сопяо1е.ыгтгеьупе(чЬ после присваивания 257: " + Ь + " — с потерей данных."); Сопво1е.игтгеЫпе()7 // Приведение типа отпг к типу яьогг без потери данных. ч = 320007 я = (яьогс) и; сопво1е.игтсептпе("в после присваивания 32000: " + Я + " — бЕЗ ПОТЕРИ Данник.ч)7 // Приведение типа п1пс к типу яьогс с потерей данных.
п = б40007 я (яЬогс) го Сопво1е.ыг1геЫпе("я после присваивания 64000: " + я + " — с потерей данных."); Сопяо1е .ИгтсеЫпе () 7 // Приведение типа 1опд к типу пупс без потери данных. 1 б40007 ов Часть ). Язык Сз и = (п1пс) 1; Сопзо1е.Игьвеььпе("и после присваивания 64000: " а и а " — без потери данных."); // Приведение типа 1опч к типу п1пс с потерей данных. 1 = -127 и = (пвпб) 1) Сопзо1е.нгвпепвпе("и после присваивания -12: " + и + " -- с потерей данных."); Сопзо1е.нг1Се11пе()7 // Приведение типа впС к типу сьаг. Ь = 88; // код АЯС11 символа Х сЬ = (пьат) Ь) Сопзо1е.нгхпесхпе("сЬ после присваивания 88: " + сп) ) ) Вот какой результат дает выполнение этой программы: Целочисленный результат деления х / у.
"3 Ь после присваивания 255: 255 -- без потери данных. Ь после присваивания 257: 1 — с потерей данных. в после присваивания 32000: 32000 — без потери данных. з после присваивания 64000; -1536 — с потерей данных. и после присваивания 64000: 64000 — без потери данных.
и после присваивания -12: 4294967284 — с потерей данных. сЬ после присваивания 88". Х Рассмотрим каждую операцию присваивания в представленном выше примере программы по отдельности. Вследствие приведения результата деления х/у к типу 1пс отбрасывается дробная часть числа, а следовательно, теряется часть информации.
Когда переменной Ь присваивается значение 255, то информация не теряется, поскольку это значение входит в-диапазон представления чисел для типа Ьубе. Но когда переменной Ь присваивается значение 257, то часть информации теряется, поскольку это значение превышает диапазон представления чисел для типа Ьубе. Приведение типов требуется в обоих случаях, поскольку неявное преобразование типа 1ПС в тип Ьубе невозможно. Когда переменной з типа зпсгс присваивается значение 32 000 переменной и типа пвпС, потери данных не происходит, поскольку это значение входит в диапазон представления чисел для типа зьсгс. Но в следующей операции присваивания переменная и имеет значение 64 000, которое оказывается вне диапазона представления чисел для типа зьсгс, и поэтому данные теряются.
Приведение типов требуется в обоих случаях, поскольку неявное преобразование типа пвпс в тип зпогс невозможно. Далее переменной и присваивается значение 64 000 переменной 1 типа 1опЯ. В этом случае данные не теряются, поскольку значение 64 000 оказывается вне диапазона представления чисел для типа п1пс. Но когда переменной и присваивается значение -12, данные теряются, поскольку отрицательные числа также оказываются вне диапазона представления чисел для типа пвпс, Приведение типов требуется в обоих случаях, так как неявное преобразование типа 1опд в тип 01пс невозможно. Глава 3.
Типы данных, литералы и переменные В9 И наконец, когда переменной спас присваивается значение типа Ьуге, информация не теряется, но приведение типов все же требуется. Преобразование типов в выражениях Помимо операций присваивания, преобразование типов происходит и в самих выражениях. В выражении можно свободно смешивать два или более типа данных, при условии их совместимости друг с другом. Например, в одном выражении допускается применение типов эпогг и 1опсн поскольку оба типа являются числовыми. Когда в выражении смешиваются разные типы данных, они преобразуются в один и тот же тип по порядку следования операций.
Преобразования типов выполняются по принятым в С№ правилам продвижения типов. Ниже приведен алгоритм, определяемый этими правилами, для операций с двумя операндами. ЕСЛИ один операнд имеет тип гтес1пта1, ТО и второй продвигается к типу гтес1тпа1 (но если второй операнд имеет тип Г1оаг илн бопЬ1е, результат будет ошибочным). ЕСЛИ один операнд имеет тип гтопЬ1е, ТО и второй продвигается к типу гтопЬ1е. ЕСЛИ один операнд имеет тип Г1оас, ТО и второй продвигается к типу 11оас.
ЕСЛИ один операнд имеет тип п1ощт, ТО и второй продвигается к типу п1оптт (но если второй операнд имеет тип зЬусе, эпогс, 1пс или 1оптт, результат будет ошибочным). ЕСЛИ один операнд имеет тнп 1опоь ТО и второй продвигается к типу 1оптт, ЕСЛИ один операнд имеет тип п1пс, а второй имеет тип эЬусе, эпогс или 1пг, ТО оба операнда продвигаются к типу 1оптт. ЕСЛИ один операнд имеет тип пупс, ТО и второй продвигается к типу и№пс. ИНАЧЕ оба операнда продвигаются к типу 1пг.
Относительно правил продвижения типов необходимо сделать ряд важных замечаний. Во-первых, не все типы могут смешиваться в выражении. В частности, неявное преобразование типа 11оаг или гтопЬ1е в тип ттес1лта1 невозможно, как, впрочем, и смешение типа п1оптт с любым целочисленным типом со знаком. Для смешения этих типов требуется явное их приведение.
Во-вторых, особого внимания требует последнее из приведенных выше правил. Оно гласит: если ни одно из предыдущих правил не применяется, то все операнды продвигаются к типу ьпг. Следовательно, все значения типа сваг, эЬуге, Ьуге, пэпогг и эпогг продвигаются к типу 1пс в целях вычисления выражения. Такое продвижение типов называется целочисленным. Это также означает, что результат выполнения всех арифметических операций будет иметь тип не ниже 1пс. Следует иметь в виду, что правила продвижения типов применяются только к значениям, которыми оперируют при вычислении выражения. Так, если значение переменной типа Ьусе продвигается к типу 1пс внутри выражения, то впс выражения эта переменная по-прежнему относится к типу Ьуге.
Продвижение типов затрагивает только вычисление выражения. 90 Часть ), Язык 0» Но продвижение типов может иногда привести к неожиданным результатам. Если, например, в арифметической операции используются два значения типа ьуге, то происходит следующее. Сначала операнды типа Ьусе продвигаются к типу 1пг. А затем выполняется операция, дающая результат типа ьпг..
Следовательно, результат выполнения операции, в которой участвуют два значения типа Ьуге, будет иметь тип »пс. Но ведь это не тот результат, который можно было бы с очевидностью предположить. Рассмотрим следующий пример программы: // Пример неожиданного результата продвижения типов! аязом Зуягеи( с1аяя Ргоипеио ( ясак»о то»с Мазо() ( Ьуге Ь; Ь = 1О; Ь = (Ьгве) (Ь * Ы к // Необнодиио приведение типов!! Совяо1е.игзсеъьпе("Ь: "+ Ь)/ ) Как ни стрг(нно, но когда результат вычисления выражения Ь*Ь присваивается обратно переменной Ь, то возникает потребность в приведении к типу ьусе( Объясняется это тем, что в выражении Ь*Ь значение переменной Ь продвигается к типу зпс и поэтому не может быть присвоено переменной типа Ьусе без приведения типов.
Имейте это обстоятельство в виду, если получите неожиданное сообщение об ошибке несовместимости типов в выражениях, которые, на первый взгляд, кажутся совершенно правильными. Аналогичная ситуация возникает при выполнении операций с символьными операндами. Например, в следующем фрагменте кода требуется обратное приведение к типу снаг, поскольку операнды сЫ и сЬ2 в выражении продвигаются к типу »пыл сваг сЫ = 'а', сь2 = 'Ь'; сЫ = (сваг) (сЫ + сь2); Без приведения типов результат сложения операндов сЫ и сЬ2 будет иметь тип 1пг, и поэтому его нельзя присвоить переменной типа снах. Продвижение типов происходит и при выполнении унарных операций, например с унарным минусом.
Операнды унарных операций более мелкого типа, чем 1пг (Ьуге, яьусе, яьогс и ияьогг), т.е. с более узким диапазоном представления чисел, продвигаются к типу ьпг.. То же самое происходит и с операндом типа сьаг. Кроме того, если выполняется унарная операция отрицания значения типа пзпс, то результат продвигается к типу 1опо. Приведение типов в выражениях Приведение типов можно применять и к отдельным частям крупного выражения.
Это позволяет точнее управлять преобразованиями типов при вычислении выражения. Рассмотрим следующий пример программы, в которой выводятся квадратные корни чисел от 1 до 10 и отдельно целые и дробные части каждого числового результата. Для этого в данной программе применяется приведение типов, благодаря которому результат, возвращаемый методом Магн. Зг(гг (), преобразуется в тип 1пг.
Глава 3. Типы данных, литералы и переменные 91 // Пример приведения типов в выражениях. махна зуатезт с1авз СаатЕхрх ( впав1с толи Ма1п() ( бопЬ1е и) Лот(п = 1.07 и <= 107 и++) ( Сопзо1е.итавеьхпе( "Квадратный корень из (О) равен (1)", и, МаСЬ.зт(хе(п))7 Сопво1е~их1пе11пе("Дробная часть числа: (О)", месь.загс(п) — (1пс) месь.зохс(п) )7 Сопзо1е.илаве11пе()' Вот как выглядит результат выполнения этой программы: квадратный корень из Целая часть числа: 1 Дробная часть числа: 1 равен 1 2 равен 1.4142135623731 0.414213562373095 3 равен 1.73205080756888 0.732050807568877 Квадратный корень из Целая часть числа: 1 Дробная часть числа: Квадратный корень из Целая часть числа: 1 Дробная часть числа: Квадратный корень из Целая часть числа: 2 Дробная часть числа: 4 равен 2 Квадратный корень из Целая часть числа: 2 Дробная часть числа: 5 равен 2.23606797749979 0.23606797749979 б равен 2.44948974278318 0.449489742783178 7 равен 2.64575131106459 0.645751311064591 8 равен 2.82842712474619 0.82842712474619 Квадратный корень из Целая часть числа: 2 Дробная часть числа: Квадратный корень из Целая часть числа: 2 Дробная часть числа: Квадратный корень из Целая часть числа.