说起来,Delphi 自 2009 引和泛型已经很长时间了,而 Delphi 缺少位域也已经更久远了,早在远古之前……,扯远了:)
新版的 Delphi 提供了一个类,名字叫 TBits,好吧,顾名思意,可是为什么是类呀?这意味着我们没法像C++一样将它嵌入到结构体里,如果你能,你就上天了@
好吧,为了实现这一目的,本着为了人类和平的思想,所以提供了 TQBits 的模板封装,几句代码:
首先看声明:
TQBits < T >= record // private var Data: T; public function GetBit(const AIndex: Integer): Boolean;inline; procedure SetBit(const AIndex: Integer; const Value: Boolean);inline; property Bits[const AIndex: Integer]: Boolean read GetBit write SetBit;default; end;
接下来看实现:
{ TQBits<T> } function TQBits<T>.GetBit(const AIndex: Integer): Boolean; begin Result := (PByte(@Data)[AIndex shr 3] and (1 shl (AIndex and $7))) <> 0; end; procedure TQBits<T>.SetBit(const AIndex: Integer; const Value: Boolean); var p: PByte; begin p := PByte(IntPtr(@Data) + (AIndex shr 3)); if Value then p^ := p^ or (1 shl (AIndex and $7)) else p^ := p^ and (not(1 shl (AIndex and $7))); end;
最后当然是测试用例:
procedure Test; var B8:TQBits<Byte>; B16:TQBits<Word>; B24:TQBits<array[0..2] of Byte>; B32:TQBits<Integer>; begin B8.Data:=0; B8[0]:=true; B8[7]:=true; assert(Sizeof(B8)=1); B16.Data:=0; B16[8]:=true; assert(SizeOf(B16)=2); FillChar(B24,SizeOf(B24),0); B24[23]:=true; assert(SizeOf(B24)=3); B32.Data:=0; B32[31]:=true; assert(SizeOf(B32)=4); end;
蛋扯完了,大家有媳妇抱媳妇,没媳妇抱大腿去吧。这个例子实际上演示的还有另一个目的,就是给大家提供下泛型使用的另一种思路,正常 Delphi 中的泛型类型支持能力实在是有限,但我们可以在实现的时候,将其类型具体化,取地址,转类型指针,然后再操作。看不懂的就算了,扯乎~~~