RuLibrary.com

ГЛАВНАЯ | ПОИСК | ТОП | КАРТА САЙТА      

 
 


 

Керниган Ричи >> Язык C (страница 27)


Ряд операций может в зависимости от своих операндов вы- зывать преобразование значение операнда из одного типа в другой. В этом разделе объясняются результаты, которые сле- дует ожидать от таких преобразований. В п. 14.6 Подводятся итоги преобразований, требуемые большинством обычных опера- ций; эти сведения дополняются необходимым образом при обсуж- дении каждой операции.

14.1. Символы и целые

Символ или короткое целое можно использовать всюду, где можно использовать целое. Во всех случаях значение преобра- зуется к целому. Преобразование более короткого целого к бо- лее длинному всегда сопровождается знаковым расширением; це- лые являются величинами со знаком. Осуществляется или нет знаковое расширение для символов, зависит от используемой машины, но гарантируется, что член стандартного набора сим- волов неотрицателен. из всех машин, рассматриваемых в этом руководстве, только PDP-11 осуществляет знаковое расширение. область значений символьных переменных на PDP-11 меняется от -128 до 127; символы из набора ASC11 имеют положительные значения. Символьная константа, заданная с помощью восьме- ричной условной последовательности, подвергается знаковому расширению и может оказаться отрицательной; например, '\377' имеет значение -1.

Когда более длинное целое преобразуется в более короткое или в CHAR, оно обрезается слева; лишние биты просто отбра- сываются.

14.2. Типы FLOAT и DOUBLE

Вся плавающая арифметика в "C" выполняется с двойной точностью каждый раз, когда объект типа FLOAT появляется в выражении, он удлиняется до DOUBLE посредством добавления нулей в его дробную часть. когда объект типа DOUBLE должен быть преобразован к типу FLOAT, например, при присваивании, перед усечением DOUBLE округляется до длины FLOAT.

14.3. Плавающие и целочисленные величины

Преобразование плавающих значений к целочисленному типу имеет тенденцию быть до некоторой степени машинно-зависимым; в частности направление усечения отрицательных чисел меняет- ся от машине к машине. Результат не определен, если значение не помещается в предоставляемое пространство.

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

14.4. Указатели и целые

Целое или длинное целое может быть прибавлено к указате- лю или вычтено из него; в этом случае первая величина преоб- разуется так, как указывается в разделе описания операции сложения.

Два указателя на объекты одинакового типа могут быть вычтены; в этом случае результат преобразуется к целому, как указывается в разделе описания операции вычитания.

14.5. Целое без знака

Всякий раз, когда целое без знака объединяется с простым целым, простое целое преобразуется в целое без знака и ре- зультат оказывается целым без знака. Значением является наи- меньшее целое без знака, соответствующее целому со знаком (по модулю 2**размер слова). В двоичном дополнительном пред- ставлении это преобразование является чисто умозрительным и не изменяет фактическую комбинацию битов.

Когда целое без знака преобразуется к типу LONG, значе- ние результата совпадает со значением целого без знака. Та- ким образом, это преобразование сводится к добавлению нулей слева.

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

Подавляющее большинство операций вызывает преобразование и определяет типы результата аналогичным образом. Приводимая ниже схема в дальнейшем будет называться "обычными арифмети- ческими преобразованиями". Сначала любые операнды типа CHAR или SHORT преобразуются в

INT, а любые операнды типа FLOAT преобразуются в DOUBLE. Затем, если какой-либо операнд имеет тип DOUBLE, то другой

преобразуется к типу DOUBLE, и это будет типом результата. В противном случае, если какой-либо операнд имеет тип LONG,

то другой операнд преобразуется к типу LONG, и это и будет

типом результата. В противном случае, если какой-либо операнд имеет тип

UNSIGNED, то другой операнд преобразуется к типу UNSIGNED,

и это будет типом результата. В противном случае оба операнда будут иметь тип INT, и это

будет типом результата.

15. Выражения

Старшинство операций в выражениях совпадает с порядком следования основных подразделов настоящего раздела, начиная с самого высокого уровня старшинства. Так, например, выраже- ниями, указываемыми в качестве операндов операции + (п.15.4), Являются выражения, определенные в п.п.15.1-15.3. Внутри каждого подраздела операции имеет одинаковое старшин- ство. В каждом подразделе для описываемых там операций ука- зывается их ассоциативность слева или справа. Старшинство и ассоциативность всех операций в выражениях резюмируются в грамматической сводке в п.18.

В противном случае порядок вычислений выражений не опре- делен. В частности, компилятор считает себя в праве вычис- лять подвыражения в том порядке, который он находит наиболее эффективным, даже если эти подвыражения приводят к побочным эффектам. Порядок, в котором происходят побочные эффекты, не специфицируется. Выражения, включающие коммутативные и ассо- циативные операции ( *,+,&,!,^ ), могут быть переупорядочены произвольным образом даже при наличии круглых скобок; чтобы вынудить определенный порядок вычислений, в этом случае не- обходимо использовать явные промежуточные переменные.

При вычислении выражений обработка переполнения и про- верка при делении являются машинно-зависимыми. Все существу- ющие реализации языка "C" игнорируют переполнение целых; об- работка ситуаций при делении на 0 и при всех особых случаях с плавающими числами меняется от машины к машине и обычно выполняется с помощью библиотечной функции.

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

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

Первичное выражение:

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

константа

строка

(выражение)

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

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

первичное-L-значение . Идентификатор

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

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

выражение

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

Идентификатор является первичным выражением при условии, что он описан подходящим образом, как это обсуждается ниже. тип идентификатора определяется его описанием. Если, однако, ти- пом идентификатора является "массив ...", то значением выра- жения, состоящего из этого идентификатора , является указа- тель на первый объект в этом массиве, а типом выражения бу- дет "указатель на ...". Более того, идентификатор массива не является выражением L-значения. подобным образом идентифика- тор, который описан как "функция, возвращающая ...", за иск- лючением того случая, когда он используется в позиции имени функции при обращении, преобразуется в "указатель на функ- цию, которая возвращает ...".

Константа является первичным выражением. В зависимости от ее формы типом константы может быть INT, LONG или DOUBLE.

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

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

Первичное выражение, за которым следует выражение в квадратных скобках, является первичным выражением. Интуитив- но ясно, что это выражение с индексом. Обычно первичное вы- ражение имеет тип "указатель на ...", индексное выражение имеет тип INT, а типом результата является "...". Выражение E1[E2] по определению идентично выражению * ((E1) + (E2)). Все, что необходимо для понимания этой записи, содержится в этом разделе; вопросы, связанные с понятием идентификаторов и операций * и + рассматриваются в п.п. 15.1, 15.2 И 15.4 соответственно; выводы суммируются ниже в п. 22.3.

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

Перед обращением любые фактические аргументы типа FLOAT преобразуются к типу DOUBLE, любые аргументы типа CHAR или SHORT преобразуются к типу INT, и, как обычно, имена масси- вов преобразуются в указатели. Никакие другие преобразования не выполняются автоматически; в частности, не сравнивает ти- пы фактических аргументов с типами формальных аргументов. Если преобразование необходимо, используйте явный перевод типа (CAST); см. П.п. 15.2, 16.7.

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

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

Первичное выражение, за которым следует точка и иденти- фикатор, является выражением. Первое выражение должно быть L-значением, именующим структуру или объединение, а иденти- фикатор должен быть именем члена структуры или объединения. Результатом является L-значение, ссылающееся на поименован- ный член структуры или объединения.

Первичное выражение, за которым следует стрелка (состав- ленная из знаков - и >) и идентификатор, является выражени- ем. первое выражение должно быть указателем на структуру или объединение, а идентификатор должен именовать член этой структуры или объединения. Результатом является L-значение, ссылающееся на поименованный член структуры или объединения, на который указывает указательное выражение.

Следовательно, выражение E1->MOS является тем же самым, что и выражение (*E1).MOS. Структуры и объединения рассмат- риваются в п. 16.5. Приведенные здесь правила использования структур и объединений не навязываются строго, для того что- бы иметь возможность обойти механизм типов. См. П. 22.1.

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

Выражение с унарными операциями группируется справо на- лево.

Унарное-выражение:

* выражение

& L-значение

- выражение

! Выражение

\^ выражение

++ L-значение

-- L-значение

L-значение ++

L-значение --

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

SIZEOF выражение

SIZEOF имя-типа

Унарная операция * означает косвенную адресацию: выраже- ние должно быть указателем, а результатом является L-значе- ние, ссылающееся на тот объект, на который указывает выраже- ние. Если типом выражения является "указатель на...", то ти- пом результата будет "...".

Результатом унарной операции & является указатель на объект, к которому ссылается L-значение. Если L-значение имеет тип "...", то типом результата будет "указатель на ...".

Результатом унарной операции - (минус) является ее опе- ранд, взятый с противоположным знаком. Для величины типа UNSIGNED результат получается вычитанием ее значения из 2**N (два в степени N), где N-число битов в INT. Унарной операции + (плюс) не существует.

Результатом операции логического отрицания ! Является 1, если значение ее операнда равно 0, и 0, если значение ее операнда отлично от нуля. Результат имеет тип INT. Эта опе- рация применима к любому арифметическому типу или указате- лям.

Операция \^ дает обратный код, или дополнение до едини- цы, своего операнда. Выполняются обычные арифметические пре- образования. Операнд должен быть целочисленного типа.

Объект, на который ссылается операнд L-значения префикс- ной операции ++, увеличивается. значением является новое значение операнда, но это не L-значение. Выражение ++х экви- валентно х+=1. Информацию о преобразованиях смотри в разборе операции сложения (п. 15.4) и операции присваивания (п. 15.14).

Префиксная операция -- аналогична префиксной операции ++, но приводит к уменьшению своего операнда L-значения.

При применении постфиксной операции ++ к L-значению ре- зультатом является значение объекта, на который ссылается L-значение. После того, как результат принят к сведению, объект увеличивается точно таким же образом, как и в случае префиксной операции ++. Результат имеет тот же тип, что и выражение L-значения.

При применении постфиксной операции -- к L-значению ре- зультатом является значение объекта, на который ссылается L-значение. После того, как результат принят к сведению, объект уменьшается точно таким же образом, как и в случае префиксной операции --. Результат имеет тот же тип, что и выражение L-значения.

Заключенное в круглые скобки имя типа данных,стоящее пе- ред выражением , вызывает преобразование значения этого вы- ражения к указанному типу. Эта конструкция называется пере- вод (CAST). Имена типов описываются в п. 16.7.

Операция SIZEOF выдает размер своего операнда в байтах. (Понятие байт в языке не определено, разве только как значе- ние операции SIZEOF. Однако во всех существующих реализациях байтом является пространство, необходимое для хранения объекта типа CHAR). При применении к массиву результатом яв- ляется полное число байтов в массиве. Размер определяется из описаний объектов в выражении. Это выражение семантически является целой константой и может быть использовано в любом месте, где требуется константа. Основное применение эта опе- рация находит при связях с процедурами, подобным распредели- телям памяти, и в системах ввода- вывода.

Название книги: Язык C
Автор: Керниган Ричи
Просмотрено 45093 раз

123456789101112131415161718192021222324252627282930313233


 
Page generation 0.003 seconds
заказать социальное такси для инвалидов в москве