DELPHI中記錄的儲存方式

2021-06-23 09:14:57 字數 4275 閱讀 8739

在delphi中,我們用record關鍵字來表明乙個記錄,有時候,我們還會看到用packed record來宣告的記錄,這二者的區別就在於儲存方式的不同;在windows中,記憶體的分配一次是4個位元組的,而packed按位元組進行記憶體的申請和分配,這樣速度要慢一些,因為需要額外的時間來進行指標的定位。因此如果不用packed的話,delphi將按一次4個位元組的方式申請記憶體,因此如果乙個變數沒有4個位元組寬的話也要佔4個位元組!這樣浪費了一些空間,但提高了效率。

例如乙個記錄,以,sizeof(okwary)應該得到8。而如果使用packed關鍵字,那麼sizeof(okwary)則得到5。

typeokwary=record

age : integer;

*** : shortint;    

end;

其中age是integer型別,正好4個位元組,而***是showint型別,占用乙個位元組,但基於4位元組得記憶體分配方式,這裡它也將占用4個位元組。

delphi中的變體記錄

在delphi中,觀察tmessage和ttypedata的定義,從關鍵字record,你一眼就可以看出,它是乙個記錄型別,但仔細觀察,你又會發現在它的定義中出現了case關鍵字。它代表什麼呢?

它代表此記錄是變體記錄。讓我們先去了解一下變體記錄。

乙個典型的變體記錄定義如下:

typerecordtypename  =record

fieldlist1:  type1;  

...  

fieldlistn:  typen;  

casetag:  ordinaltypeof

constantlist1:  (variant1);  

...  

constantlistn:  (variantn);  

end

其中case到結尾部分定義了多個變體字段。所有變體字段共享一段記憶體大小又最大變體字段決定。

使用變體記錄時要注意: 

(1)long  string、widestring、dynamic  array、inte***ce的大小都是指標大小,  olevariant其實就是com  sdk中的variant結構,大小是16位元組。

但在object  pascal中它們都需要自動終結化,如果它們出現在variant  part中,編譯器就無法知道它們是否應該進行終結化――因為不知道當前儲存的是哪種型別。   

(2)所有變體字段共享一段記憶體。而共享記憶體的大小則由最大變體字段決定。 

(3)當tag存在時,它也是記錄的乙個字段。也可以沒有tag。 

(4)記錄的變體部分的條件域必須是有序型別

(5)記錄型別中可以含有變體部分,有點象case語句,但沒有最後的end,變體部分必需在記錄中其他欄位的宣告之後

事實上delphi中記憶體的幾乎所有的變體記錄都有乙個特點(儘管這不是要求的),就是所有變體部份長度部和都是一樣的,比如:

tmessage =packed record

msg: cardinal;

caseinteger of

0: (

wparam: longint;

lparam: longint;

result: longint);

1: (

wparamlo: word;

wparamhi: word;

lparamlo: word;

lparamhi: word;

resultlo: word;

resulthi: word);

end;

wparam,lparam,result三個欄位的長度和是12個位元組,而wparamlo,wparamhi,lparamlo,lparamhi,resultlo,resulthi六個欄位之和也是12個字元,同時仔細觀察,會發現後面六個欄位中的每兩個欄位與前面三個欄位中的每乙個欄位都是對應的.

再看看trect =packed record

case integer of

0: (left, top, right, bottom: longint);

1: (topleft, bottomright: tpoint);

end;

是不是也是一樣的呢?

變體記錄得作用

(1)節約空間。對於那些要根據條件而決定是否儲存得型別,完全可以利用變體記錄來達到節約空間得效果。例如,乙個公司的員工薪水可以是月薪、年薪等方式,那麼並沒有必要在記錄中都分配空間而又用不到。

(2)型別的轉換。例如,如果有乙個64位的整數型別作為變體的第乙個字段,乙個32位的整數integer型別作為另乙個變體的第乙個字段,那麼可以向64欄位賦值然後以整數integer欄位讀出其前32位

//假如有這樣乙個員工登記表

typetpersonrec =record

id: integer;            

casebooleanof

true:  (a: cardinal); 

false: (b: word);     

end;

var

personrec: tpersonrec;

begin

showmessage(inttostr(sizeof(tpersonrec))); 

//賦值測試:

personrec.

id := 110

;personrec.

a  := 100000

; //取值:

showmessage(inttostr(personrec.

a)); 

//但是:

showmessage(inttostr(personrec.

b)); 

end;

type

tpersonrec =record

id: integer;

casetag: booleanof

true:  (a: cardinal);

false: (b: word);

end;

var

personrec: tpersonrec;

begin

personrec.

id  := 110

;personrec.

tag := true;

personrec.

a   := 100000

; personrec.

id  := 111

;personrec.

tag := false;

personrec.

b   := 100

;    

end;

//最經典的變體結構莫過於 delphi 定義的 tmessage 結構了, 兩組資料分分合合都是一體, 多麼巧妙啊!

tmessage =packed

record

msg: cardinal;

caseintegerof

0: (

wparam: longint;

lparam: longint;

result: longint);

1: (

wparamlo: word;

wparamhi: word;

lparamlo: word;

lparamhi: word;

resultlo: word;

resulthi: word);

end;

Delphi中如何呼叫儲存過程

估計有很多朋友用delphi寫過與sql server 2000資料結合的一些mis系統,對於大量的資料儲存,及資料更新.常常考慮到用儲存過程來實現.今天我寫了乙個簡單的例子,希望能給一些朋友一點幫助.1 當然,我們要在sql server 2000中建好我們的資料庫及資料表。我這裡用的資料庫是re...

Delphi中ADO處理資料的幾種方式的速度比較

ado dataprovide clientdataset 插入1000行資料需要2.078秒 ado直接sql命令 3.400秒 ado的批量方式 啟動事務 1.328秒 不使用事務1.553秒 adoquery的locktype屬性為ltbatchoptimistic cursortype為st...

delphi儲存過程的使用

摘要 delphi儲存過程的使用例項 建立儲存過程主要用sql語句create procedure來實現,並用 exec語句 儲存過程名 來執行已建立的儲存過程。儲存過程 1 建立儲存過程 建立儲存過程主要用sql語句create procedure來實現,並用 exec語句 儲存過程名 來執行已建...