Главная Случайная страница


Полезное:

Как сделать разговор полезным и приятным Как сделать объемную звезду своими руками Как сделать то, что делать не хочется? Как сделать погремушку Как сделать так чтобы женщины сами знакомились с вами Как сделать идею коммерческой Как сделать хорошую растяжку ног? Как сделать наш разум здоровым? Как сделать, чтобы люди обманывали меньше Вопрос 4. Как сделать так, чтобы вас уважали и ценили? Как сделать лучше себе и другим людям Как сделать свидание интересным?


Категории:

АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника






Преобразование типов





 

Если в выражениях встречаются операнды различных типов,

то они преобразуются к общему типу в соответствии с неболь-

шим набором правил. В общем, автоматически производятся

только преобразования, имеющие смысл, такие как, например,

преобразование целого в плавающее в выражениях типа F+I. Вы-

ражения же, лишенные смысла, такие как использование пере-

менной типа FLOAT в качестве индекса, запрещены.

Во-первых, типы CHAR и INT могут свободно смешиваться в

арифметических выражениях: каждая переменная типа CHAR авто-

матически преобразуется в INT. Это обеспечивает значительную

гибкость при проведении определенных преобразований симво-

лов. Примером может служить функция ATOI, которая ставит в

соответствие строке цифр ее численный эквивалент.

ATOI(S) /* CONVERT S TO INTEGER */

CHAR S[];

{

INT I, N;

 

N = 0;

FOR (I = 0; S[I]>='0' && S[I]<='9'; ++I)

N = 10 * N + S[I] - '0';

RETURN(N);

}

 

KAK Уже обсуждалось в главе 1, выражение

 

S[I] - '0'

 

имеет численное значение находящегося в S[I] символа, потому

что значение символов '0', '1' и т.д. образуют возрастающую

последовательность расположенных подряд целых положительных

чисел.

Другой пример преобразования CHAR в INT дает функция

LOWER, преобразующая данную прописную букву в строчную. Если

выступающий в качестве аргумента символ не является пропис-

ной буквой, то LOWER возвращает его неизменным. Приводимая

ниже программа справедлива только для набора символов ASCII.

 

LOWER(C) /* CONVERT C TO LOWER CASE; ASCII ONLY */

INT C;

{

IF (C >= 'A' && C <= 'Z')

RETURN(C + '@' - 'A');

ELSE /*@ Записано вместо 'A' строчного*/

RETURN(C);

}

 

Эта функция правильно работает при коде ASCII, потому что

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

строчным буквам, отличаются на постоянную величину, а каждый

алфавит является сплошным - между а и Z нет ничего, кроме

букв. Это последнее замечание для набора символов EBCDIC

систем IBM 360/370 оказывается несправедливым, в силу чего

эта программа на таких системах работает неправильно - она

преобразует не только буквы.

При преобразовании символьных переменных в целые возни-

кает один тонкий момент. Дело в том, что сам язык не указы-

вает, должны ли переменным типа CHAR соответствовать числен-

ные значения со знаком или без знака. Может ли при преобра-

зовании CHAR в INT получиться отрицательное целое? К сожале-

нию, ответ на этот вопрос меняется от машины к машине, отра-

жая расхождения в их архитектуре. На некоторых машинах

(PDP-11, например) переменная типа CHAR, крайний левый бит

которой содержит 1, преобразуется в отрицательное целое

("знаковое расширение"). На других машинах такое преобразо-

вание сопровождается добавлением нулей с левого края, в ре-

зультате чего всегда получается положительное число.

 

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

стандартного набора символов машины никогда не даст отрица-

тельного числа, так что эти символы можно свободно использо-

вать в выражениях как положительные величины. Но произволь-

ные комбинации двоичных знаков, хранящиеся как символьные

переменные на некоторых машинах, могут дать отрицательные

значения, а на других положительные.

Наиболее типичным примером возникновения такой ситуации

является сучай, когда значение 1 используется в качестве

EOF. Рассмотрим программу

 

CHAR C;

C = GETCHAR();

IF (C == EOF)

...

 

На машине, которая не осуществляет знакового расширения,

переменная 'с' всегда положительна, поскольку она описана

как CHAR, а так как EOF отрицательно, то условие никогда не

выполняется. Чтобы избежать такой ситуации, мы всегда пре-

дусмотрительно использовали INT вместо CHAR для любой пере-

менной, получающей значение от GETCHAR.

Основная же причина использования INT вместо CHAR не

связана с каким-либо вопросом о возможном знаковом расшире-

нии. просто функция GETCHAR должна передавать все возможные

символы (чтобы ее можно было использовать для произвольного

ввода) и, кроме того, отличающееся значение EOF. Следова-

тельно значение EOF не может быть представлено как CHAR, а

должно храниться как INT.

Другой полезной формой автоматического преобразования

типов является то, что выражения отношения, подобные I>J, и


логические выражения, связанные операциями && и \!\!, по оп-

ределению имеют значение 1, если они истинны, и 0, если они

ложны. Таким образом, присваивание

 

ISDIGIT = C >= '0' && C <= '9';

 

полагает ISDIGIT равным 1, если с - цифра, и равным 0 в про-

тивном случае. (В проверочной части операторов IF, WHILE,

FOR и т.д. "Истинно" просто означает "не нуль").

Неявные арифметические преобразования работают в основ-

ном, как и ожидается. В общих чертах, если операция типа +

или *, которая связывает два операнда (бинарная операция),

имеет операнды разных типов, то перед выполнением операции

"низший" тип преобразуется к "высшему" и получается резуль-

тат "высшего" типа. Более точно, к каждой арифметической

операции применяется следующая последовательность правил

преобразования.

- Типы CHAR и SHORT преобразуются в INT, а FLOAT в

DOUBLE.

 

- Затем, если один из операндов имеет тип DOUBLE, то

другой преобразуется в DOUBLE, и результат имеет тип DOUBLE.

- В противном случае, если один из операндов имеет тип

LONG, то другой преобразуется в LONG, и результат имеет тип

LONG.

- В противном случае, если один из операндов имеет тип

UNSIGNED, то другой преобразуется в UNSIGNED и результат

имеет тип UNSIGNED.

- В противном случае операнды должны быть типа INT, и

результат имеет тип INT.

Подчеркнем, что все переменные типа FLOAT в выражениях пре-

образуются в DOUBLE; в "C" вся плавающая арифметика выполня-

ется с двойной точностью.

Преобразования возникают и при присваиваниях; значение

правой части преобразуется к типу левой, который и является

типом результата. Символьные переменные преобразуются в це-

лые либо со знаковым расширением,либо без него, как описано

выше. Обратное преобразование INT в CHAR ведет себя хорошо -

лишние биты высокого порядка просто отбрасываются. Таким об-

разом

 

INT I;

CHAR C;

 

I = C;

C = I;

 

значение 'с' не изменяется. Это верно независимо от того,

вовлекается ли знаковое расширение или нет.

Если х типа FLOAT, а I типа INT, то как

 

х = I;

так и

I = х;

 

приводят к преобразованиям; при этом FLOAT преобразуется в

INT отбрасыванием дробной части. Тип DOUBLE преобразуется во

FLOAT округлением. Длинные целые преобразуются в более ко-

роткие целые и в переменные типа CHAR посредством отбрасыва-

ния лишних битов высокого порядка.

Так как аргумент функции является выражением, то при пе-

редаче функциям аргументов также происходит преобразование

типов: в частности, CHAR и SHORT становятся INT, а FLOAT

становится DOUBLE. Именно поэтому мы описывали аргументы

функций как INT и DOUBLE даже тогда, когда обращались к ним

с переменными типа CHAR и FLOAT.

Наконец, в любом выражении может быть осуществлено

("принуждено") явное преобразование типа с помощью конструк-

ции, называемой перевод (CAST). В этой конструкции, имеющей

вид

 

(имя типа) выражение

Выражение преобразуется к указанному типу по правилам

преобразования, изложенным выше. Фактически точный смысл

операции перевода можно описать следующим образом: выражение


как бы присваивается некоторой переменной указанного типа,

которая затем используется вместо всей конструкции. Напри-

мер, библиотечная процедура SQRT ожидает аргумента типа

DOUBLE и выдаст бессмысленный ответ, если к ней по небреж-

ности обратятся с чем-нибудь иным. таким образом, если N -

целое, то выражение

 

SQRT((DOUBLE) N)

 

до передачи аргумента функции SQRT преобразует N к типу

DOUBLE. (Отметим, что операция перевод преобразует значение

N в надлежащий тип; фактическое содержание переменной N при

этом не изменяется). Операция перевода имрация перевода име-

ет тот же уровень старшинства, что и другие унарные опера-

ции, как указывается в таблице в конце этой главы.

 







Date: 2015-09-17; view: 372; Нарушение авторских прав



mydocx.ru - 2015-2024 year. (0.017 sec.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав - Пожаловаться на публикацию