Арифметические преобразования

Подавляющее большинство операций вызывает преобразова-ние и определяет типы результата аналогичным образом. Приво-димая ниже схема в дальнейшем будет называться "обычнымиарифметическими преобразованиями". Сначала любые операндытипа char или short преобразуются в int, а любые операндытипа float преобразуются в double. Затем, если какой-либооперанд имеет тип double, то другой преобразуется к типу double, и это будет типом результата. В противном случае,если какой-либо операнд имеет тип long, то другой операндпреобразуется к типу long, и это и будет типом результата.В противном случае, если какой-либо операнд имеет тип unsigned, то другой операнд преобразуется к типу unsigned, иэто будет типом результата. В противном случае оба операндабудут иметь тип int, и это будет типом результата.

* 4. ВЫРАЖЕНИЯ

Старшинство операций в выражениях совпадает с порядкомследования основных подразделов настоящего раздела, начинаяс самого высокого уровня старшинства. Так, например, выраже-ниями, указываемыми в качестве операндов операции + (п.0.4),являются выражения, определенные в п.п.0.1-0.3. Внутри каж-дого подраздела операции имеют одинаковое старшинство. Вкаждом подразделе для описываемых там операций указываетсяих ассоциативность слева или справа. Старшинство и ассоциа-тивность всех операций в выражениях резюмируются в граммати-ческой сводке в приложении. В противном случае порядок вычислений выражений неопределен. В частности, компилятор может вычислять подвыра-жения в том порядке, который он находит наиболее эффектив-ным, даже если эти подвыражения приводят к побочным эффек-там. Порядок, в котором происходят побочные эффекты, не спе-цифицируется. Выражения, включающие коммутативные и ассоциа-тивные операции (*, +, &, |, ^), могут быть переупорядочены про-извольным образом даже при наличии круглых скобок; в этомслучае необходимо использовать явные промежуточные перемен-ные. При вычислении выражений обработка переполнения и про-верка при делении являются машинно-зависимыми. Большинствореализаций языка Си (в том числе и в ОС ДЕМОС) игнорируютпереполнение целых; обработка ошибки при делении на 0 и привсех особых случаях в операциях с вещественными числамименяется от машины к машине и обычно выполняется с помощьюбиблиотечной функции. -10-

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

Первичные выражения, включающие., - >, индексацию иобращения к функциям, группируются слева направо. первичное выражение: идентификатор константа строка (выражение) первичное _ выражение [ выражение ] первичное _ выражение (список _ выражений) необ первичное _ l _ значение. Идентификатор первичное _ выражение -> идентификатор список _ выражений: выражение список _ выражений, выражение Идентификатор является первичным выражением при условии, чтоон описан подходящим образом, как это обсуждается ниже. Типидентификатора определяется его описанием. Если, однако,типом идентификатора является массив..., то значением выра-жения, состоящего из этого идентификатора, является указа-тель на первый объект в этом массиве, а типом выражениябудет указатель на.... Более того, идентификатор массива неявляется выражением l_значения. Подобным образом интерпрети-руется идентификатор, который описан как функция, возвращаю-щая.... За исключением того случая, когда он используется впозиции имени функции при обращении, преобразуется в указа-тель на функцию, которая возвращает.... Константа является первичным выражением. В зависимостиот ее формы типом константы может быть int, long или double. Строка является первичным выражением. Исходным ее типомявляется массив символов; но следуя тем же самым правилам,которые приведены выше для идентификаторов, он модифициру-ется в указатель на символы, и результатом является указа-тель на первый символ строки. (Имеется исключение в некото-рых инициализаторах; см. ниже.) Выражение в круглых скобках является первичным выраже-нием, тип и значение которого идентичны типу и значениюэтого выражения без скобок. Наличие круглых скобок не вли-яет на то, является ли выражение l_значением или нет. Первичное выражение, за которым следует выражение вквадратных скобках, является первичным выражением. Это выра-жение с индексом. Обычно первичное выражение имеет тип ука-затель на..., индексное выражение имеет тип int, а типомрезультата является "...". Выражение e1 [ e2 ] по определениюидентично выражению * ((e1) + (e2)). Все, что необходимо -11- для понимания этой записи, содержится в этом разделе; воп-росы, связанные с понятием идентификаторов и операций * и + рассматриваются в п.п. 0.1, 0.2 и 0.4 соответственно; выводысуммируются ниже. Обращение к функции является первичным выражением, закоторым следует заключенный в круглые скобки возможно пустойсписок выражений, разделенных запятыми, которые и представ-ляют собой фактические аргументы функции. Первичное выраже-ние должно быть типа функция, возвращающая..., а результатобращения к функции имеет тип "...". Как указывается ниже,ранее не встречавщийся идентификатор, за которым непосредст-венно следует левая круглая скобка, считается описанным поконтексту, как представляющий функцию, возвращающую целое;следовательно чаще всего встречающийся случай функции, возв-ращающей целое значение, не нуждается в описании. Перед обращением любые фактические аргументы типа float преобразуются к типу double, любые аргументы типа char или short преобразуются к типу int, и, как обычно, имена масси-вов преобразуются в указатели. Никакие другие преобразованияне выполняются автоматически; в частности, не сравниваютсятипы фактических аргументов с типами формальных аргументов.Если преобразование необходимо, используйте явное преобразо-вание. При подготовке к вызову функции делается копия каждогофактического параметра; таким образом, все передачи аргумен-тов в языке Си осуществляются строго по значению. Функцияможет изменять значения своих формальных параметров, но этиизменения не влияют на значения фактических параметров. Сдругой стороны, имеется возможность передавать указатель,при этом функция может изменять значение объекта, на которыйэтот указатель указывает. Порядок вычисления аргументов вязыке не определен; различные компиляторы вычисляют по раз-ному. Допускаются рекурсивные обращения к любой функции. Первичное выражение, за которым следует точка и иденти-фикатор, является выражением. Первое выражение должно бытьl_значением, именующим структуру или объединение, а иденти-фикатор должен быть именем члена структуры или объединения.Результатом является l_значение, ссылающееся на поименован-ный член структуры или объединения. Первичное выражение, за которым следует стрелка (сос-тавленная из знаков - и >) и идентификатор, является выраже-нием. Первое выражение должно быть указателем на структуруили объединение, а идентификатор должен именовать член этойструктуры или объединения. Результатом является l_значение,ссылающееся на поименованный член структуры или объединения,на который указывает указательное выражение. -12- Следовательно, выражение e1- > mos является тем же самым,что и выражение (*e1) .mos. Структуры и объединения рассмат-риваются ниже. Приведенные здесь правила использованияструктур и объединений не навязываются строго, для тогочтобы иметь возможность обойти механизм типов (см. "Допол-нительная информация о типах").

Унарные операции

Выражение с унарными операциями группируется справаналево. унарное _ выражение: * выражение & l _ значение - выражение! выражение ~ выражение ++ l _ значение -- l _ значение l _ значение ++ l _ значение -- (имя - типа) выражение sizeof выражение sizeof (имя _ типа) Унарная операция * означает косвенную адресацию: выражениедолжно быть указателем, а результатом является l_значение,ссылающееся на тот объект, на который указывает выражение.Если типом выражения является указатель на..., то типомрезультата будет "...". Результатом унарной операции & является указатель наобъект, к которому ссылается l_значение. Если l_значениеимеет тип "...", то типом результата будет указатель на.... Результатом унарной операции - (минус) является ее опе-ранд, взятый с противоположным знаком. Для величины типа unsigned результат получается вычитанием ее значения из 2**n(два в степени n), где n-число битов в int. Унарной операции + (плюс) не существует. Результатом операции логического отрицания! является1, если значение ее операнда равно 0, и 0, если значение ееоперанда отлично от нуля. Результат имеет тип int. Эта опе-рация применима к любому арифметическому типу или указате-лям. Операция ~ (символ "тильда", находится на клавише ^ внижнем регистре) дает обратный код (или дополнение до еди-ницы) своего операнда. Выполняются обычные арифметическиепреобразования. Операнд должен быть целочисленного типа. -13- Объект, на который ссылается операнд l_значения пре-фиксной операции ++, увеличивается. Значением является новоезначение операнда, но это не l_значение. Выражение ++х экви-валентно х += 1. Информацию о преобразованиях смотри в раз-боре операции сложения (п. 0.4) и операции присваивания (п.0.14). Префиксная операция -- аналогична префиксной операции ++, но приводит к уменьшению своего операнда l_значения. При применении постфиксной операции ++ к l_значениюрезультатом является значение объекта, на который ссылаетсяl_значение. После того, как результат принят к сведению,объект увеличивается точно таким же образом, как и в случаепрефиксной операции ++. Результат имеет тот же тип, что ивыражение l_значения. При применении постфиксной операции -- к l_значениюрезультатом является значение объекта, на который ссылаетсяl_значение. После того, как результат принят к сведению,объект уменьшается точно таким же образом, как и в случаепрефиксной операции --. Результат имеет тот же тип, что ивыражение l_значения. Заключенное в круглые скобки имя типа данных, стоящееперед выражением, вызывает преобразование значения этоговыражения к указанному типу. Эта конструкция называетсяперевод (cast). Имена типов описываются в следующем разделе. Операция sizeof выдает размер своего операнда в байта.(Понятие байт в языке не определено, разве только, как зна-чение операции sizeof. Однако во всех существующих реализа-циях байтом является пространство, необходимое для храненияобъекта типа char). При применении к массиву результатомявляется полное число байтов в массиве. Размер определяетсяиз описаний объектов в выражении. Это выражение семантическиявляется целой константой и может быть использовано в любомместе, где требуется константа. Основное применение эта опе-рация находит при вызове процедур, подобных распределителямпамяти, и в системах ввода- вывода. Операция sizeof может быть также применена и к заклю-ченному в круглые скобки имени типа. В этом случае онавыдает размер в байтах объекта указанного типа. Конструкция sizeof (тип) рассматривается как целое, такчто выражение sizeof (тип) - 2 эквивалентно выражению(sizeof (тип)) - 2.

Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: