Полезное:
Как сделать разговор полезным и приятным
Как сделать объемную звезду своими руками
Как сделать то, что делать не хочется?
Как сделать погремушку
Как сделать так чтобы женщины сами знакомились с вами
Как сделать идею коммерческой
Как сделать хорошую растяжку ног?
Как сделать наш разум здоровым?
Как сделать, чтобы люди обманывали меньше
Вопрос 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; Нарушение авторских прав |