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.