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



ЗНАЕТЕ ЛИ ВЫ?

Массивы, указатели и индексация

Поиск
Каждый раз, когда идентификатор, имеющий тип массива,появляется в выражении, он преобразуется в указатель на пер-вый член этого массива. Из-за этого преобразования массивыне являются L-значениями. По определению операция индексация[] интерпретируется таким образом, что E1[E2] считаетсяидентичным выражению *((е1)+(е2)). Согласно правилам преоб-разований, применяемым при операции +, если E1 - массив, ае2 - целое, то е1[е2] ссылается на е2-й член массива е1. По-этому несмотря на несимметричный вид операция индексации яв-ляется коммутативной. В случае многомерных массивов применяется последователь-ное правило. Если е является N-мерным массивом размераI*J*...*K, то при появлении в выражении е преобразуется вуказатель на (N-1)-мерный массив размера J*...*K. Если опе-рация * либо явно, либо неявно, как результат индексации,применяется к этому указателю, то результатом операции будетуказанный (N-1)-мерный массив, который сам немедленно преоб-разуется в указатель. Рассмотрим, например, описание INT X[3][5]; Здесь X массив целых размера 3*5. При появлении в выраженииX преобразуется в указатель на первый из трех массивов из 5целых. В выражении X[I], которое эквивалентно *(X+I), снача-ла X преобразуется в указатель так, как описано выше; затемI преобразуется к типу X, что вызывает умножение I на длинуобъекта, на который указывает указатель, а именно на 5 целыхобъектов. Результаты складываются, и применение косвеннойадресации дает массив (из 5 целых), который в свою очередьпреобразуется в указатель на первое из этих целых. Если ввыражение входит и другой индекс, то таже самая аргументацияприменяется снова; результатом на этот раз будет целое. Из всего этого следует, что массивы в языке "C" хранятсяпострочно (последний индекс изменяется быстрее всего) и чтопервый индекс в описании помогает определить общее количест-во памяти, требуемое для хранения массива, но не играет ни-какой другой роли в вычислениях, связанных с индексацией.

22.4. Явные преобразования указателей

Разрешаются определенные преобразования, с использовани-ем указателей, но они имеют некоторые зависящие от конкрет-ной реализации аспекты. Все эти преобразования задаются спомощью операции явного преобразования типа; см. П. 15.2 и16.7. Указатель может быть преобразован в любой из целочислен-ных типов, достаточно большой для его хранения. Требуется липри этом INT или LONG, зависит от конкретной машины. Преоб-разующая функция также является машинно-зависимой, но онабудет вполне естественной для тех, кто знает структуру адре-сации в машине. Детали для некоторых конкретных машин приво-дятся ниже. Объект целочисленного типа может быть явным образом пре-образован в указатель. такое преобразование всегда переводитпреобразованное из указателя целое в тот же самый указатель,но в других случаях оно будет машинно-зависимым. Указатель на один тип может быть преобразован в указа-тель на другой тип. Если преобразуемый указатель не указыва-ет на объекты, которые подходящим образом выравнены в памя-ти, то результирующий указатель может при использовании вы-зывать ошибки адресации. Гарантируется, что указатель наобъект заданного размера может быть преобразован в указательна объект меньшего размера и снова обратно, не претерпев приэтом изменения. Например, процедура распределения памяти могла бы прини-мать запрос на размер выделяемого объекта в байтах, а возв-ращать указатель на символы; это можно было бы использоватьследующим образом. EXTERN CHAR *ALLOC(); DOUBLE *DP; DP=(DOUBLE*) ALLOC(SIZEOF(DOUBLE)); *DP=22.0/7.0; Функция ALLOC должна обеспечивать (машинно-зависимым спосо-бом), что возвращаемое ею значение будет подходящим для пре-образования в указатель на DOUBLE; в таком случае использо-вание этой функции будет переносимым. Представление указателя на PDP-11 соответствует 16-бито-вому целому и измеряется в байтах. Объекты типа CHAR не име-ют никаких ограничений на выравнивание; все остальные объек-ты должны иметь четные адреса. На HONEYWELL 6000 указатель соответствует 36-битовомуцелому; слову соответствует 18 левых битов и два непосредст-венно примыкающих к ним справа бита, которые выделяют символв слове. Таким образом, указатели на символы измеряются вединицах 2 в степени 16 байтов; все остальное измеряется вединицах 2 в степени 18 машинных слов. Величины типа DOUBLEи содержащие их агрегаты должны выравниваться по четным ад-ресам слов (0 по модулю 2 в степени 19). Эвм IBM 370 иINTERDATA 8/32 сходны между собой. На обеих машинах адресаизмеряются в байтах; элементарные объекты должны быть выров-нены по границе, равной их длине, так что указатели на SHORTдолжны быть кратны двум, на INT и FLOAT - четырем и наDOUBLE - восьми. Агрегаты выравниваются по самой строгойгранице, требуемой каким-либо из их элементов.

Константные выражения

В нескольких местах в языке "C" требуются выражения, ко-торые после вычисления становятся константами: после вариан-тного префикса CASE, в качестве границ массивов и в инициа-лизаторах. В первых двух случаях выражение может содержатьтолько целые константы, символьные константы и выраженияSIZEOF, возможно связанные либо бинарными операциями + - * /. % & \! Ч << >> == 1= <> <= >= либо унарными операциями - \^ либо тернарной операцией?: Круглые скобки могут использоваться для группировки, но недля обращения к функциям. В случае инициализаторов допускается большая (ударениена букву о) свобода; кроме перечисленных выше константныхвыражений можно также применять унарную операцию & к внешнимили статическим объектам и к внешним или статическим масси-вам, имеющим в качестве индексов константное выражение.Унарная операция & может быть также применена неявно, в ре-зультате появления неиндексированных массивов и функций. Ос-новное правило заключается в том, что после вычисления ини-циализатор должен становится либо константой, либо адресомранее описанного внешнего или статического объекта плюс илиминус константа.

Соображения о переносимости

Некоторые части языка "C" по своей сути машинно-зависи-мы. Следующие ниже перечисление потенциальных трудностей хо-тя и не являются всеобъемлющими, но выделяет основные изних. Как показала практика, вопросы, целиком связанные с ап-паратным оборудованием, такие как размер слова, свойстваплавающей арифметики и целого деления, не представляют осо-бенных затруднений. Другие аспекты аппаратных средств нахо-дят свое отражение в различных реализациях. Некоторые изних, в частности, знаковое расширение (преобразующее отрица-тельный символ в отрицательное целое) и порядок, в которомпомещаются байты в слове, представляют собой неприятность,которая должна тщательно отслеживаться. Большинство из ос-тальных проблем этого типа не вызывает сколько-нибудь значи-тельных затруднений. Число переменных типа REGISTER, которое фактически можетбыть помещено в регистры, меняется от машины к машине, такжекак и набор допустимых для них типов. Тем не менее все ком-пиляторы на своих машинах работают надлежащим образом; лиш-ние или недопустимые регистровые описания игнорируются. Некоторые трудности возникают только при использованиисомнительной практики программирования. Писать программы,которые зависят от каких- либо этих свойств, является чрез-вычайно неразумным. Языком не указывается порядок вычисления аргументов фун-кций; они вычисляются справа налево на PDP-11 и VAX-11 ислева направо на остальных машинах. порядок, в котором про-исходят побочные эффекты, также не специфицируется. Так как символьные константы в действительности являютсяобъектами типа INT, допускается использование символьныхконстант, состоящих из нескольких символов. Однако, посколь-ку порядок, в котором символы приписываются к слову, меняет-ся от машины к машине, конкретная реализация оказываетсявесьма машинно-зависимой. Присваивание полей к словам и символов к целым осуществ-ляется справо налево на PDP-11 и VAX-11 и слева направо надругих машинах. эти различия незаметны для изолированныхпрограмм, в которых не разрешено смешивать типы (преобразуя,например, указатель на INT в указатель на CHAR и затем про-веряя указываемую память), но должны учитываться при согла-совании с накладываемыми извне схемами памяти. Язык, принятый на различных компиляторах, отличаетсятолько незначительными деталями. Самое заметное отличие сос-тоит в том, что используемый в настоящее время компилятор наPDP-11 не инициализирует структуры, которые содержат полябитов, и не допускает некоторые операции присваивания в оп-ределенных контекстах, связанных с использованием значенияприсваивания.

Анахронизмы

Так как язык "C" является развивающимся языком, в старыхпрограммах можно встретить некоторые устаревшие конструкции.Хотя большинство версий компилятора поддерживает такие анах-ронизмы, они в конце концов исчезнут, оставив за собой толь-ко проблемы переносимости. В ранних версиях "C" для проблем присваивания использо-валась форма =ON, а не ON=, приводя к двусмысленностям, ти-пичным примером которых является X = -1 где X фактически уменьшается, поскольку операции = и - при-мыкают друг к другу, но что вполне могло рассматриваться икак присваивание -1 к X. Синтаксис инициализаторов изменился: раньше знак равенс-тва, с которого начинается инициализатор, отсутствовал, такчто вместо INT X = 1; использовалось INT X 1; изменение было внесено из-за инициализации INT F (1+2) которая достаточно сильно напоминает определение функции,чтобы смутить компиляторы.


Поделиться:


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

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