Арифметические операции

Язык С
Учебное введение Оператор FOR Копирование файла Подсчет строк Массивы Аргументы - вызов по значению Область действия: внешние переменные Резюме Константы Арифметические операции Затем, если один из операндов имеет тип DOUBLE, то другой преобразуется в DOUBLE, и результат имеет тип DOUBLE Побитовые логические операции Условные выражения Поток управления Переключатель Цикл DO - WHILE Оператор GOTO и метки Функции, возвращающие нецелые значения Внешние переменные Правила, определяющие область действия Статические переменные Инициализация Препроцессор языка “C” Указатели и адреса Адресная арифметика Указатели символов и функции Многомерные массивы Инициализация массивов указателей Структуры Массивы сруктур Указатели на структуры Поиск в таблице Объединения Ввод и вывод Средства ввода/вывода не являются составной частью языка “с”, так что мы не выделяли их в нашем предыдущем изложении Форматный вывод - функция PRINTF Обычные символы (не %), которые предполагаются совпадающими со следующими отличными от символов пустых промежутков символами входного потока Форматное преобразование в памяти Низкоуровневый ввод/вывод - операторы READ и WRITE Произвольный доступ - SEEK и LSEEK Пример - распределитель памяти Лексические соглашения Имеется шесть классов лексем: идентификаторы, ключевые слова, константы, строки, операции и другие разделители Характеристики аппаратных средств Следующая ниже таблица суммирует некоторые свойства аппаратного оборудования, которые меняются от машины к машине Первичные выражения Первичные выражения, включающие ., ->, индексацию и обращения к функциям, группируются слева направо Унарные операции Выражение с унарными операциями группируется справо налево Операции равенства Выражение-равенства: выражение == выражение выражение != выражение Операция запятая Выражение-с-запятой: выражение , выражение Внешние определения данных Снова о типах В этом разделе обобщаются сведения об операциях, которые можно применять только к объектам определенных типов Анахронизмы Так как язык “C” является развивающимся языком, в старых программах можно встретить некоторые устаревшие конструкции
424070
знаков
0
таблиц
0
изображений

2.5. Арифметические операции.

Бинарными арифметическими операциями являются +, -, *, / и операция деления по модулю %. Имеется унарная операция -, но не существует унарной операции +.

При делении целых дробная часть отбрасывается. Выражение X % Y дает остаток от деления X на Y и, следовательно, равно нулю, когда х делится на Y точно. Например, год является високосным, если он делится на 4, но не делится на 100, исключая то, что делящиеся на 400 годы тоже являются високосными. Поэтому

IF(YEAR % 4 == 0 && YEAR % 100 != 0 !! YEAR % 400 == 0) год високосный ELSE год невисокосный

Операцию % нельзя использовать с типами FLOAT или DOUBLE.

Операции + и - имеют одинаковое старшинство, которое младше одинакового уровня старшинства операций *, / и %, которые в свою очередь младше унарного минуса. Арифметические операции группируются слева направо. (Сведения о старшинстве и ассоциативности всех операций собраны в таблице в конце этой главы). Порядок выполнения ассоциативных и коммутативных операций типа + и - не фиксируется; компилятор может перегруппировывать даже заключенные в круглые скобки выражения, связанные такими операциями. таким образом, а+(B+C) может быть вычислено как (A+B)+C. Это редко приводит к какому-либо расхождению, но если необходимо обеспечить строго определенный порядок, то нужно использовать явные промежуточные переменные.

Действия, предпринимаемые при переполнении и антипереполнении (т.е. При получении слишком маленького по абсолютной величине числа), зависят от используемой машины.

2.6. Операции отношения и логические операции

Операциями отношения являются

=> > =< <

все они имеют одинаковое старшинство. Непосредственно за ними по уровню старшинства следуют операции равенства и неравенства:

== !=

которые тоже имеют одинаковое старшинство. операции отношения младше арифметических операций, так что выражения типа I<LIM-1 понимаются как I<(LIM-1), как и предполагается.

Логические связки && и !! более интересны. Выражения, связанные операциями && и !!, вычисляются слева направо, причем их рассмотрение прекращается сразу же как только становится ясно, будет ли результат истиной или ложью. учет этих свойств очень существенен для написания правильно работающих программ. Рассмотрим, например, оператор цикла в считывающей строку функции GETLINE, которую мы написали в главе 1.

FOR(I=0;I<LIM-1 && (C=GETCHAR()) != 'N' && C != EOF; ++I) S[I]=C;

Ясно, что перед считыванием нового символа необходимо проверить, имеется ли еще место в массиве S, так что условие I<LIM-1 должно проверяться первым. И если это условие не выполняется, мы не должны считывать следующий символ.

Так же неудачным было бы сравнение 'C' с EOF до обращения к функции GETCHAR : прежде чем проверять символ, его нужно считать.

Старшинство операции && выше, чем у !!, и обе они младше операций отношения и равенства. Поэтому такие выражения, как

I<LIM-1 && (C = GETCHAR()) != 'N' && C != EOF не нуждаются в дополнительных круглых скобках. Но так как операция != старше операции присваивания, то для достижения правильного результата в выражении

(C = GETCHAR()) != 'N' кобки необходимы.

Унарная операция отрицания ! Преобразует ненулевой или истинный операнд в 0, а нулевой или ложный операнд в 1.

Обычное использование операции ! Заключается в записи

IF( ! INWORD ) Вместо IF( INWORD == 0 ) Tрудно сказать, какая форма лучше. Конструкции типа ! INWORD Читаются довольно удобно (“если не в слове”). Но в более сложных случаях они могут оказаться трудными для понимания.

Упражнение 2-1.

Напишите оператор цикла, эквивалентный приведенному выше оператору FOR, не используя операции &&.

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

Если в выражениях встречаются операнды различных типов, то они преобразуются к общему типу в соответствии с небольшим набором правил. В общем, автоматически производятся только преобразования, имеющие смысл, такие как, например, преобразование целого в плавающее в выражениях типа 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© /* CONVERT C TO LOWER CASE; ASCII ONLY */ INT C;

{ IF ( C >= 'A' && C <= 'Z' ) RETURN( C + '@' - 'A');

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

RETURN©;

}

Эта функция правильно работает при коде 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.


Информация о работе «Язык С»
Раздел: Информатика, программирование
Количество знаков с пробелами: 424070
Количество таблиц: 0
Количество изображений: 0

Похожие работы

Скачать
48443
0
0

... основаниям. При этом философская абстракция языка оказывается неразрывно связана с основными темами и движениями философии в целом. Более конкретно, на ранние стадии традиционно рассматриваемого в рамках АФ анализа обыденного языка глубокое влияние оказала философия Дж. Э. Мура, особенно его учение о здравом смысле, согласно которому такие понятия, как «человек», «мир», «я», «внешний мир», « ...

Скачать
43709
0
0

... и других странах СНГ, а также облегчение доступа к русской и мировой культуре и науке. Таким образом, судя по данным наших исследований, востребованность русского языка осталась в республике достаточно высокой. Многие представители современной молдавской молодежи продолжают, как их отцы и деды, тянуться к русской культуре, научным и техническим достижениям России. Русский язык остается языком ...

Скачать
39778
0
1

... рисуночное словесно-слоговое письмо). Памятники среднеэламского периода (14—12 вв. до н.э.) выполнены аккадской клинописью. Памятники новоэламского периода относятся к 8—6 вв. до н.э. Был официальным языком в персидском государстве Ахеменидов в 6—4 вв. предполагается, что он, подвергшись влиянию древнеперсидского, сохранился до раннего средневековья. 7. Бурушаски язык Язык бурушаски ( ...

Скачать
64931
0
0

... /диалект), скифский, согдийский, среднеперсидский, таджикский, таджриши (язык/диалект), талышский, татский, хорезмийский, хотаносакский, шугнано-рушанская группа языков, ягнобский, язгулямский и др. Они относятся к индоиранской ветви индоевропейских языков. Области распространения: Иран, Афганистан, Таджикистан, некоторые районы Ирака, Турции, Пакистана, Индии, Грузии, Российской Федерации. Общее ...

0 комментариев


Наверх