|
問題來源: http://www.cnblogs.com/del/archive/2009/03/01/1032376.html#1464477 假如有這樣三種結(jié)構(gòu), 分別來描述: 直線、圓與三角形: 上面三個結(jié)構(gòu)的數(shù)據(jù)有類似之處, 在實用中常常需要用一個綜合的結(jié)構(gòu)替代它們; 這就像 Delphi 中的 TWMKey、TWMMouse、TWMClose 等近 200 個結(jié)構(gòu)都可以用 TMessage 代替一樣. 下面是一個非常不好, 但容易理解的描述: TMyShape = packed record ID: Integer; x1, y1, x2, y2: Integer; x, y, r: Integer; xa, ya, xb, yb, xc, yc: Integer; end; //此結(jié)構(gòu)大小是 56 字節(jié) //之所以說它不好是因浪費太多, 譬如記錄一個圓, 只需要 ID、x、y、r 四個字段, 會浪費其它 10 個字段. //但如果需要一個結(jié)構(gòu)同時描述一條直線、一個圓、一個三角的話, 這個結(jié)構(gòu)是合適的; 這里討論的并不是這種情況. 我們在某一時刻只需要它來表示一個形狀(或者是直線、或者是圓、或者是三角); 假如我們讓結(jié)構(gòu)按照最大的需要分配空間, 譬如三角需要最多(除 ID 外, 是 6*4 個字節(jié)), 就分配 24 字節(jié); 這個空間用來記錄一個圓或者直線也是足夠的. Delphi 允許我們使用這樣的語法來定義(這就是所謂的變體結(jié)構(gòu)): 把上面這種描述用表格表示一下:
對這樣的一個結(jié)構(gòu)變量(譬如是 rec: TMyShape)來講, 不管你是不是需要, rec.ID、rec.x1 ... rec.yc 等所有結(jié)構(gòu)成員都是存在的; 但有些數(shù)據(jù)是共享一塊內(nèi)存, 譬如 x1、x、xa 共享 4 個字節(jié); x2、r、xb 共享 4 個字節(jié), 這可以測試一下: 咱們的 "彬" 朋友不明白的是 case Integer of ... 這里的 case 并不是咱們經(jīng)常用的 case 語句(譬如它沒有 end;), 只是 Delphi 的語法規(guī)定而已; case Integer of 中的 Integer 也沒有再占用 4 字節(jié)的空間(但接下了的例子會占用), 也只是語法形式. 考慮另一個問題: 我們僅從一個結(jié)構(gòu)變量的數(shù)據(jù)能看出它具體描述的圖形類型嗎? 應(yīng)該說: 這不容易看出; 其實, 在實用中我們很少會有這種要求. 假如非要從結(jié)構(gòu)數(shù)據(jù)中識別圖形類型也可以, Delphi 提供了語法支持, 但這又要多占幾個字節(jié): TMyShape = packed record ID: Integer; case flag: Integer of 0: (x1, y1, x2, y2: Integer); 1: (x, y, r: Integer); 2: (xa, ya, xb, yb, xc, yc: Integer); end; //此時的結(jié)構(gòu)大小應(yīng)該是 32 字節(jié). //像這樣, flag 也是一個結(jié)構(gòu)成員, 也可以讀寫; 我們可以給 flag 賦不同的值以區(qū)別圖形類型. //但不管 flag 這個值是什么, 都不會影響前面的內(nèi)存共享機制; flag 也不會因為其他賦值而自動改變. 根據(jù)不同的需要, 上面的 flag 也可以是其他類型(譬如枚舉); 我也經(jīng)常見到 case Boolean of 的用法, 這只能用在兩種可選狀態(tài)的情形, 譬如: TMyShape = packed record ID: Integer; case Boolean of True: (x1, y1, x2, y2: Integer); False: (x, y, r: Integer); end; Delphi 還有一個相近的概念 absolute(從變量的層面上共享內(nèi)存), 參見: http://www.cnblogs.com/del/archive/2009/02/19/1394037.html |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|