(тип элементов может быть и любым другим), и надо скопировать тысячу элементов, начиная с первого на сто индексов выше (т.е. как бы сдвинуть значения с первого на сто первый индекс). Обычное, но необдуманное решение проблемы — цикл FOR:

for i:=1 to 1000 do A[ i+100] := A[ i ];

который лишь испортит данные массива A. Это произойдет из-за перекрытия исходного и конечного отрезков значений (рис. 14.6).

Рис. 14.6

Здесь элементы, начиная со 101-го, будут замещены раньше, чем скопированы! Корректный цикл FOR должен быть убывающим:

for i:=1000 downto 1 do A[ i+100 ] := А[ i ];

Чтобы избежать всех этих сложностей, рекомендуем пользоваться процедурой Move. Рассматриваемая задача решается так:

Move( А[ 1 ], А[ 101 ], 1000 * SizeOf( Real ) );

При этом проблема перекрытия снимается автоматически самой процедурой Move (она выбирает направление копирования исходя из заданных параметров). Параметры A[1] и A[101] в вызове имеют смысл не значений 1-го и 101-го элементов массива A, а адресов этих элементов в памяти.

Если же понадобится вернуть 1000 элементов «назад» в первую позицию массива, вызов будет таким:

Move( А[ 101 ], А[ 1 ], 1000 * SizeOf( Real ) );

и проблема перекрытия вновь будет решена автоматически.

Помните, что никаких проверок на корректность значений параметров в Move не происходит, и если значение длины блока больше, чем может вместить переменная — адрес назначения (второй параметр Move), то будет заполнена часть памяти, отведенная под другие

- 304 -

данные, что весьма неприятно. Советуем использовать функцию SizeOf для вычисления длин блока. Выражения типа 1000*SizeOf (Real) состоят из констант и могут быть вычислены еще во время компиляции программы, так что длинные арифметические последовательности в вызове Move ничуть не замедляют работу программ.

<p>14.6. Функции обработки машинных слов Lo, Hi и Swap</p>

Среди прочих специальных средств низкого уровня Турбо Паскаль предоставляет несколько удобных функций для работы над отдельными байтами машинных слов. Некоторые системные переменные и функции Турбо Паскаля возвращают два однобайтовых значения, объединенных в тип Word. Для их «распаковки» как раз подходят описываемые здесь функции. Их три (табл. 14.1).

Таблица 14.1

Функция : Тип

Возвращаемое значение

Hi(X) : Тип-X

Старший байт аргумента X

Lo(X) : Тип-X

Младший байт аргумента X

Swap(X) : Тип-X

Число с переставленными старшим и младшим байтами

Аргумент X имеет тип Word или Integer ( 2-байтовый целый), и возвращаемое значение имеет тот же тип, что и X.

Любое число типа Word раскладывается на два слагаемых из значений своих байтов по правилу (для типа Integer эта формула не подходит)

X := Hi(X) * 256 + Lo(X);

Функция Swap возвращает число типа Word или Integer в зависимости от типа аргумента X, в котором старший и младший байты поменялись местами. Следует быть осторожным при использовании функции с аргументом типа LongInt. В версии 5.5 Турбо Паскаля компилятор «ничего не имеет против» таких вызовов, но возвращаемое значение при счете усекается до типа Word, меняя его иной раз до неузнаваемости.

<p>14.7. Вставки машинного кода в программе</p><p>14.7.1. Оператор inline</p>

Несмотря на то, что средствами Турбо Паскаля можно сделать практически все, не всегда полученный результат будет максимально

- 305 -

эффективным по быстродействию, если сравнивать с грамотно написанной программой на ассемблере. Другой вопрос, за сколько дней и ночей будет написан и отлажен ассемблерный текст, а за сколько — программы на Турбо Паскале. Все это верно и для других языков. В последних версиях языка Си можно просто писать вставки на ассемблере посреди текста Си-программ. Довольно похожим способом решена проблема включения машинных команд в текст программ на Турбо Паскале. Правда, в текущих версиях языка для того надо употреблять не мнемонические команды языка ассемблера, а их аналоги в машинном коде. Оператор вставки машинного кода записывается с помощью зарезервированного слова inline и списка кодов, разделенных косой чертой:

inline ( Код1/ Код2/ Код3/ .../ КодN );

Перейти на страницу:

Поиск

Похожие книги