Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
YAZbIki.doc
Скачиваний:
8
Добавлен:
16.03.2015
Размер:
758.78 Кб
Скачать

3.1. Операции

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

К арифметическим операциям относятся операции сложения (+), вычитания (–), умножения (*), деления (/) и деления по модулю (%) – вычисление остатка от деления. В языке отсутствует операция возведения в степень.

В одном и том же выражении могут встретиться переменные и константы разных типов, в этом случае они преобразуются к старшему типу в соответствии с приоритетами типов, установленными в языке C: long double – double – float – unsigned long – long – unsigned int – int – unsigned char – char.

В этом перечислении наивысший приоритет имеет типlong double.Компилятор преобразует “меньший” тип в “больший”. Например, если в выражении операнды имеют типыlong double,double,float и т. д., то все они на время вычислений автоматически преобразуются к старшему типу. В данном случае это будет типlong double. Тип результата будет соответствовать старшему типу в выражении.

Отметим, что в соответствии с правилами выполнения вычислений в C при делении двух операндов целого типа результат также является целочисленным и формируется путем отбрасывания дробной части частного от деления: 4/7=0; 7/4=1.

Деление по модулю выполняется над операндами целого типа и результатом операции является остаток от деления: 7%4=3; 4%7=0.

Приоритеты арифметических операций:

  • умножение, деление, деление по модулю;

  • сложение, вычитание.

Операции одного уровня выполняются слева направо.

Помимо стандартных арифметических операций используются две дополнительных операции: инкремент (++) и декремент (– –). Результатом выполнения инкремента будет увеличение значения операнда на 1, результат декремента – уменьшение операнда на 1. Обе операции идентичны, поэтому рассмотрим на примере только операцию инкремента (увеличения).

Операция инкремента реализуется в двух видах:

++х;

x++;

аналогично декремент:

––х;

x––;

где х – идентификатор переменной.

Строго говоря, ограничений на тип переменной нет, но реально эти операции работают с переменными целого типа.

Результатом операции является увеличение значения переменной х на 1, причем в первом случае х сначала увеличивается на 1, а затем используется в дальнейших операциях, а во втором – значение х сначала используется, а потом увеличивается на 1. Различие операций сказывается при использовании их в сложных выражениях. Например, определить значения x,t,z,y после вычисления выражений при х=1, t=1:

y=++x; z=t++;

Ответ: x=2; t=2; z=1; y=2.

Дополнительные арифметические операции используются, в основном, для организации счетчиков в циклах и имеют следующие ограничения:

  • операции не следует использовать по отношению к переменным, которые встречаются в выражении более одного раза, т. е. не следует использовать выражение типа х*х++;

  • операции инкремента и декремента можно применять только к переменным, а не к результату, т. е. выражение (х*y)++ неверное;

  • операции не рекомендуется использовать в логических выражениях.

Данные операции имеют более высокий приоритет по сравнению с другими арифметическими операциями.

Операции присваивания

Выражения с операциями присваивания группируются справа налево. Операций присваивания в языке C несколько. Все они требуют, чтобы левый операнд был л_значением. Тип результата операции присваивания совпадает с типом левого операнда. Результат равен значению, которое содержится в левом операнде после выполнения присваивания. Две части составного знака операции присваивания являются отдельными лексемами.

выражение_присваивания:

л_значение = выражение

л_значение += выражение

л_значение -= выражение

л_значение *= выражение

л_значение /= выражение

л_значение %= выражение

л_значение >>= выражение

л_значение <<= выражение

л_значение &= выражение

л_значение ^= выражение

л_значение |= выражение

При простом присваивании (=) значение выражения помещается в объект, обозначенный л_значением. Если оба операнда имеют арифметический тип, перед присваиванием правый операнд преобразуется к типу левого. Во-вторых, оба операнда могут быть структурами или объединениями одного типа. Наконец, если левый операнд является указателем, то и правый операнд, вообще говоря, должен быть указателем того же типа. Указателю, однако, может быть присвоена константа 0; этим гарантируется, что будет сформирован пустой указатель, отличный от любого указателя на объект.

Выражение вида E1оп= E2 почти эквивалентно E1 = E1оп(E2), однако E1 вычисляется только один раз. В выражениях += и -= левый операнд может быть указателем, в этом случае (целочисленный) правый операнд преобразуется по правилам, описанным в пункте Аддитивные операции. Все правые операнды и все левые операнды-неуказатели должны иметь арифметический тип.

Первичные выражения

Первичные выражения, содержащие ., ->, индексные конструкции и вызовы функций, группируются слева направо.

первичное_выражение:

идентификатор

константа

текстовая_константа

( выражение )

первичное_выражение [ выражение ]

первичное_выражение ( список_выражений )

первичное_выражение . идентификатор

первичное_выражение -> идентификатор

список_выражений:

выражение

список_выражений , выражение

Идентификатор является первичным выражением при условии, что он соответствующим образом описан (описания обсуждаются ниже). Тип идентификатора специфицируется в описании. Если тип идентификатора - "массив ...", то значение такого выражения есть указатель на первый объект в массиве, а тип выражения - "указатель на ...". Кроме того, идентификатор массива не является л_значением. Аналогично, идентификатор, описанный как "функция, возвращающая ...", при использовании всюду кроме позиции имени функции в конструкции вызова, преобразуется к типу "указатель на функцию, возвращающую ...".

Константа является первичным выражением. Тип константы может быть int, long или double в зависимости от ее внешнего вида. Символьные константы имеют тип int, вещественные константы имеют тип double.

Текстовая константа является первичным выражением. Первоначально ее тип - "массив символов", но, следуя правилу, сформулированному выше для идентификаторов, он преобразуется в "указатель на символ"; результатом является указатель на первый символ в текстовой константе. (Исключение составляет определенный вид инициализаторов; см. пункт Инициализация в разделе ОПИСАНИЯ).

Выражение в скобках является первичным выражением, его тип и значение совпадают с типом и значением вложенного выражения. Наличие скобок не влияет на то, будет ли выражение л_значением.

Первичное выражение, за которым следует выражение в квадратных скобках, является первичным выражением. Его интуитивный смысл - индексирование. Обычно первое выражение имеет тип "указатель на ...", выражение-индекс - int, тип результата - "...". Выражение E1[E2] тождественно (по определению) *((E1)+(E2)). Все сведения, необходимые для понимания данной записи, приводятся в этом пункте, а также в пунктах Унарные операции и Аддитивные операции в связи с обсуждением идентификаторов, * и +, соответственно. Выводы делаются в пункте Массивы, указатели и индексирование (раздел ЕЩЕ О ТИПАХ).

Вызов функции есть первичное выражение, за которым следует заключенный в скобки список (возможно пустой) выражений, являющихся фактическими параметрами функции. Первичное выражение должно иметь тип "функция, возвращающая ...", а результат вызова функции имеет тип "...". Как поясняется ниже, не встретившийся до сих пор идентификатор, за которым следует левая скобка, неявно, исходя из контекста, описывается как функция, возвращающая целый результат.

Все фактические параметры типа float преобразуются перед вызовом к типу double. Все параметры типов char или unsigned long - к int. Имена массивов преобразуются в указатели. Никаких других преобразований автоматически не делается; в частности, компилятор не сравнивает типы фактических и формальных параметров. Если преобразование необходимо, его следует задать явно (см. Унарные операции, а также пункт Имена типов в разделе ОПИСАНИЯ).

При обработке вызова функции изготавливается копия каждого фактического параметра. Таким образом, в языке C все параметры передаются только по значению. Функция может изменить значения формальных параметров, но эти изменения не повлияют на значения параметров фактических. При передаче указателей следует учитывать, что функция может изменить указуемый объект. Порядок обработки параметров в языке не определяется; отметим, что в разных компиляторах он разный. Допускаются рекурсивные вызовы любой функции.

Первичное выражение, за которым следует точка, а затем идентификатор, также является первичным. Первое выражение должно быть структурой или объединением, а идентификатор должен именовать элемент структуры или объединения. Значение выражения - названный элемент структуры или объединения; это л_значение, если первое выражение -л_значение.

Первичное выражение, за которым следует стрелка -> (составленная из знаков - и >), а затем идентификатор, также является первичным. Первое выражение должно быть указателем на структуру или объединение, а идентификатор должен именовать элемент этой структуры или объединения. Значение выражения -л_значение, обозначающее названный элемент указуемой структуры или объединения. Таким образом, выражение E1->MOS - то же самое, что и (*E1).MOS. Структуры и объединения обсуждаются в пункте Описания структур и объединений раздела ОПИСАНИЯ.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]