再說變體結構 回覆 彬 的問題

2021-09-05 20:30:11 字數 3160 閱讀 4263

假如有這樣三種結構, 分別來描述: 直線、圓與三角形:

type

tline = packed record

id: integer;

x1,y1: integer;

x2,y2: integer;

end;

tcircle = packed record

id: integer;

x,y: integer;

r: integer;

end;

t******** = packed record

id: integer;

xa,ya: integer;

xb,yb: integer;

xc,yc: integer;

end;

//無需 sizeof, 我們可以輕鬆看出三個結構的大小分別是: 20、16、28 位元組

上面三個結構的資料有類似之處, 在實用中常常需要用乙個綜合的結構替代它們;

這就像 delphi 中的 twmkey、twmmouse、twmclose 等近 200 個結構都可以用 tmessage 代替一樣.

下面是乙個非常不好, 但容易理解的描述:

tmyshape = packed record

id: integer;

x1, y1, x2, y2: integer;

x, y, r: integer;

xa, ya, xb, yb, xc, yc: integer;

end;

//此結構大小是 56 位元組

//之所以說它不好是因浪費太多, 譬如記錄乙個圓, 只需要 id、x、y、r 四個字段, 會浪費其它 10 個字段.

//但如果需要乙個結構同時描述一條直線、乙個圓、乙個三角的話, 這個結構是合適的; 這裡討論的並不是這種情況.

我們在某一時刻只需要它來表示乙個形狀(或者是直線、或者是圓、或者是三角);

假如我們讓結構按照最大的需要分配空間, 譬如三角需要最多(除 id 外, 是 6*4 個位元組), 就分配 24 位元組; 這個空間用來記錄乙個圓或者直線也是足夠的.

delphi 允許我們使用這樣的語法來定義(這就是所謂的變體結構):

tmyshape = packed record

id: integer;

case integer of

0: (x1, y1, x2, y2: integer);

1: (x, y, r: integer);

2: (xa, ya, xb, yb, xc, yc: integer);

end;

//可以這樣檢視一下: showmessage(inttostr(sizeof(tmyshape)));

//它剛好是 28 位元組, 和上面的 t******** 大小一樣.

//用這個結構可以非常方便地描述上面三種圖形; 儘管有時也會有浪費, 但相比在使用時帶來的方便, 那是可以接受的.

把上面這種描述用**表示一下:

共 28 個位元組

用於三角時

idxa

yaxb

ybxc

yc用於直線時

idx1

y1x2

y2用於圓時idx

yr對這樣的乙個結構變數(譬如是 rec: tmyshape)來講, 不管你是不是需要, rec.id、rec.x1 ... rec.yc 等所有結構成員都是存在的;

但有些資料是共享一塊記憶體, 譬如 x1、x、xa 共享 4 個位元組; x2、r、xb 共享 4 個位元組, 這可以測試一下:

type

tmyshape = packed record

id: integer;

case integer of

0: (x1, y1, x2, y2: integer);

1: (x, y, r: integer);

2: (xa, ya, xb, yb, xc, yc: integer);

end;

var rec: tmyshape;

begin

rec.r := 123;

showmessagefmt('%d, %d', [rec.x2, rec.xb]);

end;

咱們的 "彬" 朋友不明白的是 case integer of ...

這裡的 case 並不是咱們經常用的 case 語句(譬如它沒有 end;), 只是 delphi 的語法規定而已;

case integer of 中的 integer 也沒有再占用 4 位元組的空間(但接下了的例子會占用), 也只是語法形式.

考慮另乙個問題: 我們僅從乙個結構變數的資料能看出它具體描述的圖形型別嗎?

應該說: 這不容易看出; 其實, 在實用中我們很少會有這種要求.

假如非要從結構資料中識別圖形型別也可以, delphi 提供了語法支援, 但這又要多佔幾個位元組:

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;

//此時的結構大小應該是 32 位元組.

//像這樣, flag 也是乙個結構成員, 也可以讀寫; 我們可以給 flag 賦不同的值以區別圖形型別.

//但不管 flag 這個值是什麼, 都不會影響前面的記憶體共享機制; flag 也不會因為其他賦值而自動改變.

根據不同的需要, 上面的 flag 也可以是其他型別(譬如列舉);

我也經常見到 case boolean of 的用法, 這只能用在兩種可選狀態的情形, 譬如:

tmyshape = packed record

id: integer;

case boolean of

true: (x1, y1, x2, y2: integer);

false: (x, y, r: integer);

end;

delphi 還有乙個相近的概念 absolute(從變數的層面上共享記憶體), 參見:

給Double關於考研問題的回覆

把計算機領域的就業方向講了一下,先看一下。我個人要考研究生,是覺得上研究生技術上可以有很大提高,當然這樣未來的就業 薪水方面以及未來的發展也會有提高。而且自己對工作也會得到更好的滿足。我是準備去做技術的,目前的目標是嵌入式裝置的網路應用,就是現在做的那套東西。要考研究生的哪個方向,最重要的還是要看你...

文獻閱讀 梅州佛教香花的結構 文字與變體

佛教香花儀式 主要梳理廣東梅州客家香花佛事儀式的基本內容 歷史演變 香花文字中的非文字形態,呈現梅州社會普遍認可的香花結構特徵 普庵教的特點 香花是梅州特色的佛教超度儀式,是梅州客家當地佛教度亡儀式的代稱,香花的主要含義即進入齋主家庭超生度死的儀式。在梅州僧侶中,香花佛事一般被認為是明代人何南鳳編訂...

再說單例模式的執行緒安全問題

今天和同事聊起了單例模式的執行緒安全,我說如果不做任何措施,單例模式在多執行緒下是不安全的,得到的 單例 實際上並不是單例。但是為什麼不是單例呢?由此我上網查了一下,在使用單例模式時,一定要注意執行緒安全問題,之前的寫法沒有任何問題。如下 package com.xhz.singleton 單例 a...