Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Характеристики аппаратных средств

Поиск
Следующая ниже таблица суммирует некоторые свойства ап-паратного оборудования, которые меняются от машины к машине.Хотя они и влияют на переносимость программ, на практике онипредставляют маленькую проблему, чем это может казаться за-ранее. Таблица 1 ------------------------------------------------------- DEC PDP-11 HONEYWELL IBM 370 INTERDATA 8/32 ASCII ASCII EBCDIC ASCII CHAR 8 BITS 9 BITS 8 BITS 8 BITS INT 16 36 32 32 SHORT 16 36 16 16 LONG 32 36 32 32 FLOAT 32 36 32 32 DOUBLE 64 72 64 64 RANGE -38/+38 -38/+38 -76/+76 -76/+76

Синтаксическая нотация

В используемой в этом руководстве синтаксической нотациисинтаксические категории выделяются курсивом (прим. перев.:в настоящее время синтексические категории вместо курсивомвыделяются подчеркиванием), а литерные слова и символы -жирным шрифтом. Альтернативные категории перечисляются наотдельных строчках. Необязательный символ, терминальный илинетерминальный, указывается индексом "необ", так что \(выражение --------- необ \) указывает на необязательное выражение, заключенное в фигур-ных скобках. Синтаксис суммируется в пункте 18.

Что в имени тебе моем?

Язык "C" основывает интерпретацию идентификатора на двухпризнаках идентификатора: его классе памяти и его типе.Класс памяти определяет место и время хранения памяти, свя-занной с идентификатором; тип определяет смысл величин, на-ходящихся в памяти, определенной под идентификатором. Имеются четыре класса памяти: автоматическая, статичес-кая, внешняя и регистровая. Автоматические переменные явля-ются локальными для каждого вызова блока и исчезают при вы-ходе из этого блока. Статические переменные являются локаль-ными, но сохраняют свои значения для следующего входа в блокдаже после того, как управление передается за пределы блока.Внешние переменные существуют и сохраняют свои значения втечение выполнения всей программы и могут использоваться длясвязи между функциями, в том числе и между независимо ском-пилированными функциями. Регистровые переменные хранятся(ели это возможно) в быстрых регистрах машины; подобно авто-матическим переменным они являются локальными для каждогоблока и исчезают при выходе из этого блока. В языке "C" предусмотрено несколько основных типовобъектов: объекты, написанные как символы (CHAR), достаточно вели-ки, чтобы хранить любой член из соответствующего данной реа-лизации внутреннего набора символов, и если действительныйсимвол из этого набора символов хранится в символьной пере-менной, то ее значение эквивалентно целому коду этого симво-ла. В символьных переменных можно хранить и другие величины,но реализация будет машинно-зависимой. Можно использовать до трех размеров целых, описываемыхкак SHORT INT, INT и LONG INT. Длинные целые занимают неменьше памяти, чем короткие, но в конкретной реализации мо-жет оказаться, что либо короткие целые, либо длинные целые,либо те и другие будут эквивалентны простым целым. "Простые"целые имеют естественный размер, предусматриваемый архиитек-турой используемой машины; другие размеры вводятся для удво-летворения специальных потребностей. Целые без знака, описываемые как UNSIGNED, подчиняютсязаконам арифметики по модулю 2**N, где N - число битов в ихпредставлении. (На PDP-11 длинные величины без знака не пре-дусмотрены). Плавающие одинарной точности (FLOAT) и плавающие двойнойточности (DOUBLE) в некоторых реализациях могут быть синони-мами. Поскольку объекты упомянутых выше типов могут быть ра-зумно интерпретированы как числа, эти типы будут называтьсяарифметическими. типы CHAR и INT всех размеров совместно бу-дут называться целочисленными. Типы FLOAT и DOUBLE совместнобудут называться плавающими типами. Кроме основных арифметических типов существует концепту-ально бесконечный класс производных типов, которые образуют-ся из основных типов следующим образом: массивы объектов большинства типов; функции, которые возвращают объекты заданного типа; указатели на объекты данного типа; структуры, содержащие последовательность объектов различных типов; объединения, способные содержать один из нескольких объектов различных типов. Вообще говоря, эти методы построения объектов могут при-меняться рекурсивно.

Объекты и L-значения

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

14. Преобразования

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

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

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

Типы FLOAT и DOUBLE

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

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

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

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

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

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

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

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

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

Выражения

Старшинство операций в выражениях совпадает с порядкомследования основных подразделов настоящего раздела, начинаяс самого высокого уровня старшинства. Так, например, выраже-ниями, указываемыми в качестве операндов операции +(п.15.4), Являются выражения, определенные в п.п.15.1-15.3.Внутри каждого подраздела операции имеет одинаковое старшин-ство. В каждом подразделе для описываемых там операций ука-зывается их ассоциативность слева или справа. Старшинство иассоциативность всех операций в выражениях резюмируются вграмматической сводке в п.18. В противном случае порядок вычислений выражений не опре-делен. В частности, компилятор считает себя в праве вычис-лять подвыражения в том порядке, который он находит наиболееэффективным, даже если эти подвыражения приводят к побочнымэффектам. Порядок, в котором происходят побочные эффекты, неспецифицируется. Выражения, включающие коммутативные и ассо-циативные операции (*,+,&,!,^), могут быть переупорядоченыпроизвольным образом даже при наличии круглых скобок; чтобывынудить определенный порядок вычислений, в этом случае не-обходимо использовать явные промежуточные переменные. При вычислении выражений обработка переполнения и про-верка при делении являются машинно-зависимыми. Все существу-ющие реализации языка "C" игнорируют переполнение целых; об-работка ситуаций при делении на 0 и при всех особых случаяхс плавающими числами меняется от машины к машине и обычновыполняется с помощью библиотечной функции.

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

Первичные выражения, включающие., ->, индексацию и об-ращения к функциям, группируются слева направо. Первичное выражение: идентификатор константа строка (выражение) первичное-выражение [выражение] первичное-выражение (список-выражений нео первичное-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.

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

Выражение с унарными операциями группируется справо на-лево. Унарное-выражение: * выражение & 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). При применении к массиву результатом яв-ляется полное число байтов в массиве. Размер определяется изописаний объектов в выражении. Это выражение семантическиявляется целой константой и может быть использовано в любомместе, где требуется константа. Основное применение эта опе-рация находит при связях с процедурами, подобным распредели-телям памяти, и в системах ввода- вывода. Операция SIZEOF может быть также применена и к заключен-ному в круглые скобки имени типа. В этом случае она выдаетразмер в байтах объекта указанного типа. Конструкция SIZEOF (тип) рассматривается как целое, такчто выражение SIZEOF (тип) - 2 эквивалентно выражению(SIZEOF (тип)9 - 2.

Мультипликативные операции

Мультипликативные операции *, /, и % группируются слеванаправо. Выполняются обычные арифметические преобразования. Мультипликативное-выражение: выражение * выражение выражение / выражение выражение % выражение Бинарная операция * означает умножение. Операция * ассо-циативна, и выражения с несколькими умножениями на одном итом же уровне могут быть перегруппированы компилятором. Бинарная операция / означает деление. При делении поло-жительных целых осуществляется усечение по направлению к ну-лю, но если один из операндов отрицателен, то форма усечениязависит от используемой машины. На всех машинах, охватывае-мых настоящим руководством, остаток имеет тот же знак, чтои делимое. Всегда справедливо, что (A/B)*B+A%B равно A (еслиB не равно 0). Бинарная операция % выдает остаток от деления первоговыражения на второе. Выполняются обычные арифметические пре-образования. Операнды не должны быть типа FLOAT.

Аддитивные операции

Аддитивные операции + и - группируются слева направо.выполняются обычные арифметические преобразования. Для каж-дой операции имеются некоторые дополнительные возможности,связанные с типами операндов. Аддитивное-выражение: выражение + выражение выражение - выражение Результатом операции + является сумма операндов. Можно скла-дывать указатель на объект в массиве и значение любого цело-численного типа. во всех случаях последнее преобразуется вадресное смещение посредством умножения его на длину объек-та, на который указывает этот указатель. Результатом являет-ся указатель того же самого типа, что и исходный указатель,который указывает на другой объект в том же массиве, смещен-ный соответствующим образом относительно первоначальногообъекта. Таким образом, если P является указателем объекта вмассиве, то выражение P+1 является указателем на следующийобъект в этом массиве. Никакие другие комбинации типов для указателей не разре-шаются. Операция + ассоциативна, и выражение с несколькими сло-жениями на том же самом уровне могут быть переупорядоченыкомпилятором. Результатом операции - является разность операндов. Вы-полняются обычные арифметические преобразования. Кроме того,из указателя может быть вычтено значение любого целочислен-ного типа, причем, проводятся те же самые преобразования,что и при операции сложения. Если вычитаются два указателя на объекты одинакового ти-па, то результат преобразуется (делением на длину объекта) ктипу INT, представляя собой число объектов, разделяющих ука-зываемые объекты. Если эти указатели не на объекты из одногои того же массива, то такое преобразование, вообще говоря,даст неожиданные результаты, потому что даже указатели наобъекты одинакового типа не обязаны отличаться на величину,кратную длине объекта.

Операции сдвига

Операции сдвига << и >> группируются слева направо. Дляобеих операций проводятся обычные арифметические преобразо-вания их операндов, каждый из которых должен быть целочис-ленного типа. Затем правый операнд преобразуется к типу INT;результат имеет тип левого операнда. Результат не определен,если правый операнд отрицателен или больше или равен, чемдлина объекта в битах. Выражение-сдвига: выражение << выражение выражение >> выражение Значением выражения E1<>E2 яв-ляется E1, сдвинутое вправо на E2 битовых позиций. Если E1имеет тип UNSIGNE, то сдвиг вправо гарантированно будет ло-гическим (заполнение нулем); в противном случае сдвиг можетбыть (и так и есть на PDP-11) арифметическим (освобождающие-ся биты заполняются копией знакового бита).

Операции отношения

Операции отношения группируются слева направо, но этотфакт не очень полезен; выражение A<b<="" Выражение-отношения:="" означать.="" казалось="" оно="" того,="" означает=""> выражение выражение <= выражение выражение >= выражение Операции < (меньше), > (больше), <= (меньше или равно) и >=(больше или равно) все дают 0, если указанное отношение лож-но, и 1, если оно истинно. Результат имеет тип ITN. Выполня-ются обычные арифметические преобразования. Могут сравни-ваться два указателя; результат зависит от относительногорасположения указываемых объектов в адресном пространстве.Сравнение указателей переносимо только в том случае, еслиуказатели указывают на объекты из одного и того же массива.

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

Выражение-равенства: выражение == выражение выражение!= выражение Операции == (равно) и!= (не равно) в точности аналогичныоперациям отношения, за исключением того, что они имеют бо-лее низкий уровень старшинства. (Поэтому значение выраженияA

15.8. Побитовая операция 'и'

Выражение-и: выражение & выражение Операция & является ассоциативной, и включающие & выражениямогут быть переупорядочены. Выполняются обычные арифметичес-кие преобразования; результатом является побитовая функция'и' операндов. Эта операция применима только к операндам це-лочисленного типа.

15.9. Побитовая операция исключающего 'или'

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

15.10. Побитовая операция включающего 'или'

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

15.11. Логическая операция 'и'

Выражение-логического-и: выражение && выражение Операция && группируется слева направо. Она возвращает 1,если оба ее операнда отличны от нуля, и 0 в противном слу-чае. В отличие от & операция && гарантирует вычисление слеванаправо; более того, если первый операнд равен 0, то значе-ние второго операнда вообще не вычисляется. Операнды не обязаны быть одинакового типа, но каждый изних должен быть либо одного из основных типов, либо указате-лем. результат всегда имеет тип ITN.

15.12. Операция логического 'или'

Выражение-логического-или: выражение \!\! выражение Операция \!\! Группируется слева направо. Она возвращает 1,если один из операндов отличен от нуля, и 0 в противном слу-чае. В отличие от операции \! Операция \!\! Гарантирует вы-числение слева направо; более того, если первый операнд от-личен от нуля, то значение второго операнда вообще не вычис-ляется. Операнды не обязаны быть одинакового типа, но каждый изних должен быть либо одного из основных типов, либо указате-лем. Результат всегда имеет тип INT.

Условная операция

Условное-выражение: выражение? выражение: выражение Условные выражения группируются слево направо. Вычисляетсязначение первого выражения, и если оно отлично от нуля, торезультатом будет значение второго выражения; в противномслучае результатом будет значение третьего выражения. Еслиэто возможно, проводятся обычные арифметические преобразова-ния, с тем, чтобы привести второе и третье выражения к обще-му типу; в противном случае, если оба выражения являютсяуказателями одинакового типа, то результат имеет тот же тип;в противном случае одно выражение должно быть указателем, адругое - константой 0, и результат будет иметь тип указате-ля. Вычисляется только одно из второго и третьего выражений.

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

Имеется ряд операций присваивания, каждая из которыхгруппируется слева направо. Все операции требуют в качествесвоего левого операнда L-значение, а типом выражения присва-ивания является тип его левого операнда. Значением выраженияприсваивания является значение, хранимое в левом операндепосле того, как присваивание уже будет произведено. Две час-ти составной операции присваивания являются отдельными лек-семами. Выражение-присваивания: L-значение = выражение L-значение += выражение L-значение -= выражение L-значение *= выражение L-значение /= выражение L-значение %= выражение L-значение >>= выражение L-значение <<= выражение L-значение &= выражение L-значение ^= выражение L-значение \!= выражение Когда производится простое присваивание C'=', значениевыражения заменяет значение объекта, на которое ссылаетсяL-значение. Если оба операнда имеют арифметический тип, топеред присваиванием правый операнд преобразуется к типу ле-вого операнда. О свойствах выражения вида E1 оп = E2, где Oп - одна изперечисленных выше операций, можно сделать вывод, еслиучесть, что оно эквивалентно выражению E1 = E1 оп (E2); од-нако выражение E1 вычисляется только один раз. В случае опе-раций += и -= левый операнд может быть указателем, причемпри этом (целочисленный) правый операнд преобразуется такимобразом, как объяснено в п. 15.4; все правые операнды и всеотличные от указателей левые операнды должны иметь арифмети-ческий тип. Используемые в настоящее время компиляторы допускаютприсваивание указателя целому, целого указателю и указателяуказателю другого типа. такое присваивание является чистымкопированием без каких-либо преобразований. Такое употребле-ние операций присваивания является непереносимым и можетприводить к указателям, которые при использовании вызываютошибки адресации. Тем не менее гарантируется, что присваива-ние указателю константы 0 дает нулевой указатель, которыйможно отличать от указателя на любой объект.

Операция запятая

Выражение-с-запятой: выражение, выражение Пара выражений, разделенных запятой, вычисляется слева нап-раво и значение левого выражения отбрасывается. Типом и зна-чением результата является тип и значение правого операнда.Эта операция группируется слева направо. В контексте, гдезапятая имеет специальное значение, как, например, в спискефактических аргументов функций (п. 15.1) Или в списках ини-циализаторов (п. 16.6), Операция запятая, описываемая в этомразделе, может появляться только в круглых скобках; напри-мер, функция F(A,(T=3,T+2),C) имеет три аргумента, второй из которых имеет значение 5.

Описания

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

Спецификаторы класса памяти

Ниже перечисляются спецификаторы класса памяти: Спецификатор-класса-памяти: AUTO STATIC EXTERN REGISTER TYPEDEF Спецификатор TYPEDEF не реализует памяти и называется"спецификатором класса памяти" только по синтаксическим со-ображениям; это обсуждается в п. 16.8. Смысл различных клас-сов памяти был обсужден в п. 12. Описания AUTO, STATIC и REGISTER служат также в качествеопределений в том смысле, что они вызывают резервированиенужного количества памяти. В случае EXTERN должно присутст-вовать внешнее определение (п. 18) Указываемых идентификато-ров где-то вне функции, в которой они описаны. Описание REGISTER лучше всего представлять себе как опи-сание AUTO вместе с намеком компилятору, что описанные такимобразом переменные будут часто использоваться. Эффективнытолько несколько первых таких описаний. Кроме того, в регис-трах могут храниться только переменные определенных типов;на PDP-11 это INT, CHAR или указатель. Существует и другоеограничение на использование регистровых переменных: к нимнельзя применять операцию взятия адреса &. При разумном ис-пользовании регистровых описаний можно ожидать полученияменьших по размеру и более быстрых программ, но улучшение вбудущем генерирования кодов может сделать их ненужными. Описание может содержать не более одного спецификаторакласса памяти. Если описание не содержит спецификатора клас-са памяти, то считается, что он имеет значение AUTO, еслиописание находится внутри некоторой функции, и EXTERN в про-тивном случае. исключение: функции никогда не бывает автома-тическими.

Спецификаторы типа

Ниже перечисляются спецификаторы типа. Спецификатор-типа: CHAR SHORT INT LONG UNSIGNED FLOAT DOUBLE спецификатор-структуры-или-объединения определяющее-тип-имя Слова LONG, SHORT и USIGNED можно рассматривать как при-лагательные; допустимы следующие комбинации: SHORT INT LONG INT USIGNED INT LONG FLOAT Последняя комбинация означает то же, что и DOUBLE. В осталь-ном описание может содержать не более одного спецификаторатипа. Если описание не содержит спецификатора типа, то счи-тается, что он имеет значение INT. Спецификаторы структур и объединений обсуждаются в п.16.5; Описания с определяющими тип именами TYPEDEF обсужда-ются в п. 16.8.

Описатели

Входящий в описание список описателей представляет собойпоследовательность разделенных запятыми описателей, каждыйиз которых может иметь инициализатор. Список-описателей: инициализируемый-описатель инициализируемый-описатель, список-описателей инициализируемый-описатель: описатель-инициализатор необ Инициализаторы описываются в п. 16.6. Спецификаторы и описа-ния указывают тип и класс памяти объектов, на которые ссыла-ются описатели. Описатели имеют следующий синтаксис: описатель: идентификатор (описатель) * описатель описатель () описатель [константное-выражение необ] Группирование такое же как и в выражениях.

Смысл описателей

Каждый описатель рассматривается как утверждение того,что когда конструкция той же самой формы, что и описатель,появляется в выражении, то она выдает объект указанного типаи указанного класса памяти. Каждый описатель содержит ровноодин идентификатор; это именно тот идентификатор, который иописывается. Если в качестве описателя появляется просто идентифика-тор, то он имеет тип, указываемый в специфицирующем заголов-ке описания. Описатель в круглых скобках идентичен описателю безкруглых скобок, но круглые скобки могут изменять связи всоставных описателях. Примеры смотри ниже. Представим себе описание T DI где T - спецификатор типа (подобный INT и т.д.), а DI - опи-сатель. Предположим, что это описание приводит к тому, чтосоответствующий идентификатор имеет тип "...T", где "..."пусто, если DI просто отдельный идентификатор (так что тип Xв "INT X" просто INT). Тогда, если DI имеет форму *D то содержащийся идентификатор будет иметь тип "... Указательна T". Если DI имеет форму D() то содержащийся идентификатор имеет тип "... Функция, возв-ращающая T". Если DI имеет форму D[константное-выражение] или D[ ] то содержащийся идентификатор имеет тип "...массив T". Впервом случае константным выражением является выражение,значение которого можно определить во время компиляции и ко-торое имеет тип INT. (Точное определение константного выра-жения дано в п. 23). Когда несколько спецификаций вида "мас-сив из" оказываются примыкающими, то создается многомерныймассив; константное выражение, задающее границы массивов,может отсутствовать только у первого члена этой последова-тельности. Такое опускание полезно, когда массив являетсявнешним и его фактическое определение, которое выделяет па-мять, приводится в другом месте. Первое константное выраже-ние может быть опущено также тогда, когда за описателем сле-дует инициализация. В этом случае размер определяется почислу приведенных инициализируемых элементов. Массив может быть образован из элементов одного из ос-новных типов, из указателей, из структур или объединений илииз других массивов (чтобы образовать многомерный массив). Не все возможности, которые разрешены с точки зренияуказанного выше синтаксиса, фактически допустимы. Имеютсяследующие ограничения: функции не могут возвращать массивы,структуры, объединения или функции, хотя они могут возвра-щать указатели на такие вещи; не существует массивов функ-ций, хотя могут быть массивы указателей на функции. Анало-гично, структуры или объединения не могут содержать функцию,но они могут содержать указатель на функцию. В качестве примера рассмотрим описание INT I, *IP, F(), *FIP(), (*PFI)(); в котором описывается целое I, указатель IP на целое, функ-ция F, возвращающая целое, функция FIP, возвращающая указа-тель на целое, и указатель PFI на функцию, которая возвраща-ет целое. Особенно полезно сравнить два последних описателя.Связь в *FIP() можно представить в виде *(FIP()), так чтоописанием предполагается, а такой же конструкцией в выраже-нии требуется обращение к функции FIP и последующее исполь-зование косвенной адресации для выдачи с помощью полученногорезультата (указателя) целого. В описателе (*PFI)() до


Поделиться:


Последнее изменение этой страницы: 2016-08-26; просмотров: 210; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.17.183.204 (0.011 с.)