fillchar

計算機編程語言中的函數

計算機編程語言中的一個函數。

賦值函數


Pascal語言的一個內存塊賦值函數。

定義

Procedure FillChar ( Var X; Count : Longint; Value : Char or Byte);
意為:對一個Char類型的數組X進行Count次賦值,當Value為Char類型時,直接賦值;若Value為Byte類型時,將Value作為AscII賦值給每個單元。

引申

被引申為:對一個內存塊,每8個二進位位賦值Value,賦值Count次,長度為:Count*8個二進位位。
FillChar是一種很常用的過程,大部分賦值都是用FillChar完成的,因為對內存的塊賦值,比使用循環要快得多。

舉例

根據引申意,我們舉個例子:
首先定義:
Var
a : array[1..10000] of arrtype;
fillchar(a,sizeof(a),0);
一般使用fillchar時還使用了函數sizeof(),其功能是返回變數所佔的總位元組數,如上例返回:
當arrtype為
1.real sizeof(a)的值為60(每個元素佔6個位元組,10個元素共佔60個位元組)
single sizeof(a)的值為40(每個元素佔4個位元組,10個元素共佔40個位元組)
double sizeof(a)的值為80(每個元素佔8個位元組,10個元素共佔80個位元組)
extended sizeof(a)的值為100(每個元素佔10個位元組,10個元素共佔100個位元組)
comp sizeof(a)的值為80(每個元素佔8個位元組,10個元素共佔80個位元組)
2.integer(word) sizeof(a)的值為20 (每個元素佔2個位元組,10個元素共佔20個位元組)
3.byte (shortint) sizeof(a)的值為10 (每個元素佔1個位元組,10個元素共佔10個位元組)
4.longint sizeof(a)的值為40 (每個元素佔4個位元組,10個元素共佔40個位元組)
5.boolean sizeof(a)的值為10(每個元素佔1個位元組,10個元素共佔10個位元組)
6.char sizeof(a)的值為10 (每個元素佔1個位元組,10個元素共佔10個位元組)

全體賦值


我們一般是用fillchar對數組賦值,然後使用sizeof函數進行整體賦值
舉例:

FillChar(a,sizeof(a),1);

當arrtype為
1.boolean 全部為true(1是非0值,表示true)
2.char 全部為#1
3.byte,shortint 每個元素是1位元組量,全部為1
4.integer,word 每個元素是2位元組量,全部為(257)10。
5.longint 每個元素是4位元組量,全部為(16843009)10。
6.single 每個元素是4位元組量,全部為2.36942782761724E-0038
integer和word全部為257是因為:
在一個integer或word 型變數中,它的高、低兩個位元組均用1來填充(將10進位數1轉化為二進位數00000001),結果為:
高位元組 低位元組
15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 1 | 0 0 0 0 0 0 0 1
顯然,得到的量就是(257)10=(0000000100000001)2。
另:integer類型的數據是用補碼錶示的有符號數,最高位是符號位,0表示正,1表示負,
所以如果賦值導致最高位為1,就有可能變為負數。
byte,shortint類似
char是因為#1的ASCII碼為1,具體請參考ASCII碼錶或詞條ASCII
longint 全部為16843009是因為
對於每個元素來講,用1填充后變為:
最高位元組 次高位元組 次低位元組 最低位元組
31 30 29 28 27 26 25 24 | 23 22 21 20 19 18 17 16 |15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 1 | 0 0 0 0 0 0 0 1 |0 0 0 0 0 0 0 1 | 0 0 0 0 0 0 0 1
longint類型的數據是用補碼錶示的有符號數,最高位是符號位,0表示正,1表示負,由於本數是正數,故補碼、反碼及原碼均為00000001000000010000000100000001,其值為(224+216+28+1)10=( 16843009)10;
single 全部為2.36942782761724E-0038
對於每個元素來講,用1填充后的結果與longint類型的二進位碼完全相同,但是, single類型對此數據的“解釋”卻完全不同:
A.最高位(第31位)是整個數的符號位,0為正, 1為負;
B.接著的8位(第30位至第23位)是用移碼表示的階碼;
C.後面的23位(第22至第0位)表示尾數;
D.單精度量的值為:±2實際指數*實際尾數
①、若階碼=00000000,則實際指數=-126,實際尾數=(0.???????????????????????)2,其中的?代表相應位置上的二進位碼(0或1);顯然,在?全為0時, 這個單精度量的值為0;
②、若階碼大於00000000且小於11111111,則實際指數=階碼-(127)10=階碼-01111111,實際尾數=(1.???????????????????????)2
③、INF(無窮大)若階碼=11111111,尾數全0,則已達上界,被作為無窮大
④、浮點運算錯誤:若階碼=11111111,尾數在(00000000000000000000000, 10000000000000000000000)之間。
⑤、NAN(非數:Not A Number)若階碼=11111111,尾數在[10000000000000000000000, 11111111111111111111111]之間
下面,我們來分析二進位碼為00000001000000010000000100000001的單精度數(single類型)的值是多少。
①最高位為0,表示正數;
②階碼為00000010,換成10進位數為2,則實際指數=2-127=-125,
③尾數為00000010000000100000001,實際尾數=1. 00000010000000100000001, 換成10進位數為1+2-7+2-15+2-23=【1.00784313678741455078125】,
④此單精度數的值是+2-125*【1.00784313678741455078125】≈2.36942782761724e-38

FillChar(a,sizeof(a),0);

執行fillchar(a,sizeof(a),0);
當arrtype為
1.real(其他實數類型差不多) 使得a中的元素全部成為0.0
2.integer(byte,word,longint,shortint都相同) 全部為0
3.boolean 全部為false
4.char 全部為#00

FillChar(a,sizeof(a),255);

執行fillchar(a,sizeof(a),255);
當arrtype為
1.real(其他實數類型差不多) 使得a中的元素全部成為-1.0
2.integer(byte,word,longint,shortint都相同) 全部為-1
3.char 全部為#-1

附:關於集合類型

對於集合類型 若arrtype=set of '#'..'z'; 執行fillchar(a,sizeof(a),0)后的結果:a全為空集;sizeof(a)返回120。為什麼sizeof(a)的值為120?原來,對集合類型來講,由於元素範圍事先必須給定(如'#'..'z'),每個元素是否存在於某集合中,只需用0或1記下即可,用0表示該元素不屬於某集合,用1表示該元素屬於某集合,即只用1個二進位位就可表示1個元素是否屬於某集合,那麼只要我們按元素的序號順序記下一串二進位代碼,就可以標記所有範圍內的元素是否屬於某集合了。但這裡有一個問題:數據的存儲通常是以位元組為單位進行的,不是直接訪問每一個二進位位,因此,必須將用戶給定的元素的範圍進行調整,調整原則是:兩端適當外擴,使第一個元素的序號以及元素的個數正好成為8的倍數,這樣就可以位元組為單位存儲集合了。即:若arrtype=set of char1..char2(事先要定義char1,char2常量),則範圍擴大為newchar1..newchar2,其中newchar1=chr(ord(char1)-ord(char1) mod 8), newchar2=chr(ord(char2)+7-ord(char2) mod 8)。對於arrtype=set of '#'..'z',用戶給定的範圍是:#35..#122,則擴大后的實際範圍是#32..#127,元素個數為96,需要用96bit=12byte表示,故數組a中每個元素(數組中的元素)佔12位元組,共10個元素要佔120位元組。
問題:對於arrtype=set of '#'..'z'; 執行fillchar(a,sizeof(a),135)后的結果是什麼呢?(135)10= (10000111)2, 數組a中每個元素如a[1]佔12位元組,即:100001111000011110000111100001111000011110000111100001111000011110000111100001111000011110000111,共96個二進位位,最低位為1,表示擴展后範圍內的第1個集合元素(#32即空格)屬於集合a[1],第2位為1,表示第2個元素(#33即“!”)屬於集合a[1],第3位為1,表示第3個元素(#34即“"”)屬於集合a[1],第4位為0,表示第4個元素(#35即“#”)不屬於集合a[1],依此類推。其他的數組元素a[2],a[3],...,a[10]都與a[1]相同。

部分賦值


前面講的都是全部位元組被填充(因為用了sizeof()函數)
對上例,若執行fillchar(a,1,55),即將變數a的第一個位元組(下標最小的元素的最低位元組)填充為(55)10,其原理雷同。

小結


Fillchar(var X; Count: Word; value)過程的功能是,把指定變數X在內存段中所佔的第Count個位元組中的每個位元組用一個位元組的數據value來填充,由於各種數據類型對相同的二進位碼具有不同的解釋,故最後得到的結果也大相徑庭。
以下是FillChar的過程原型:
procedure FillChar(var Dest; count: Integer; Value: Char);
var
I: Integer;
P: PChar;
begin
P := PChar(@Dest);
for I := count-1 downto 0 do
P[I] := Value;
end;