14.4. Процедура заполнения FillChar
Эта процедура уже использовалась в предыдущих главах. Здесь мы обсудим ее подробно. Вызов процедуры содержит три параметра:
FillChar( VAR V; NBytes : Word; В : Byte )
или
FillChar( VAR V; NBytes : Word; С : Char )
Первый — переменная V любого типа, второй — число байтов переменной V, которые будут заполнены значением B или C. Процедура FillChar служит для заполнения участков памяти (ОЗУ) одним и тем же однобайтовым значением. Например, обнулить числовой массив A любой сложности можно одним вызовом:
FillChar( A, SizeOf( А ), 0 );
Если заполнение происходит числом, то третьим параметром должно быть значение, совместимое с типом Byte. Но если речь идет о заполнении символом, то последнее значение должно быть символьного типа. Самой процедуре FillChar этот момент безразличен, и можно для числового массива A записать
FillChar( A, SizeOf( А ), '0' );
- 300 -
но результатом здесь будет заполнение не нулем, а кодом Ord('0'), что равняется 48.
Следует также помнить, что заполняется заданным значением каждый байт блока с размером, заданным параметром NBytes. И если переменная A сконструирована не из однобайтных значений, а из более длинных (Word, Integer, Real и т.п.), то корректно работает лишь заполнение нулем. Например, заполнение переменной W типа Word вызовом
FillChar( W, SizeOf( Word ), 1 );
приведет к тому, что в W будет записано значение 257. Если надо заполнить не всю структуру, а часть ее, то следует указать идентификатор того элемента структуры, начиная с которого надо проводить заполнение. Так, можно заполнить средние элементы массива A:
VAR
А : Array [ 1..500 ] of LongInt;
BEGIN
FillChar( A[ 100 ], 200 * SizeOf( LongInt ), 0 );
...
END.
В этом примере 200 значений типа LongInt массива A, начиная с 100-го, будут заполнены нулем.
С особой осторожностью надо заполнять строки символами, так как нужно заботиться о нулевом байте строки. Подробно об этом говорилось в гл. 8 «Обработка символов и строк».
Кроме того, надо всегда следить за согласованностью реального размера переменной (первого параметра) и длины заполняемого блока (значением NBytes). Если длина блока превышает размер переменной, то будут заполнены байты ОЗУ, следующие за переменной, но к ней уже не относящиеся! Иными словами, если A — статическая переменная или разыменованная ссылка, то следует придерживаться правила
NBytes <= SizeOf( A ).
Сам Турбо Паскаль проверок на корректность параметров не производит.
То, что процедура FillChar заполняет все по байтам, не всегда удобно. В справочном руководстве по Турбо Паскалю приводится пример функции в машинных кодах, заполняющей области памяти так же, как FillChar, но значениями типа Word — по 2 байта сразу (рис. 14.4).
- 301 -
| PROCEDURE FillWord( VAR V; NWords, Fill : Word );
| BEGIN
| inline(
| $C4/$BE/ V / { LES DI, bp+V}
| $8B/$8E/ NWords/ { MOV CX, bp+NWords }
| $8B/$86/ Fill/ {MOV AX, bp+Fill}
| $FC/ { CLD }
| $F3/$AB ) { REP STOSW }
| END;
| VAR
| P : Pointer;
| BEGIN
| P := Ptr( $B800, 0 ); {Начало памяти экрана для цветных мониторов; для монохромных надо задавать P := Ptr( $8000, 0 ) }
| FillWord( Р^, 80*25, 176 + 14 * 256 );
| ReadLn
| END.
Рис. 14.4
На рис. 14.4 дан пример заполнения области экрана (размером 80x25 видимых символов) символом #176 цветом номер 14. Код и цвет скомбинированы в одно значение типа Word. При таком заполнении помните, что первым в машинном представлении слова (Word) идет младший байт, а следом за ним — старший (значение множителя при 256). Обратите внимание на разыменование указателя P, что означает передачу в FillWord адреса начала видеоизображения, а не самого значения P.