Bit manipulation/de
│
Deutsch (de) │
English (en) │
français (fr) │
Maskierte Operationen
Dieses Beispiel ist ein einfacher Ansatz zur Bit-Manipulation. Das Beispiel bietet den Vorteil, dass Operationen, mit Bit-Gruppen, auf einmal durchgeführt werden.
procedure ClearBit(var Value: QWord; Index: Byte);
begin
Value := Value and ((1 shl Index) xor High(QWord)));
end;
procedure SetBit(var Value: QWord; Index: Byte);
begin
Value := Value or (QWord(State) shl Index);
end;
procedure PutBit(var Value: QWord; Index: Byte; State: Boolean);
begin
Value := (Value and ((1 shl Index) xor High(QWord))) or (QWord(State) shl Index);
end;
function GetBit(Value: QWord; Index: Byte): Boolean;
begin
Result := ((Value shr Index) and 1) = 1;
end;
Bitpacked record
Die Verwendung von bitpacked records, wird durch die lokale Compilerdirektive {$BITPACKING ON} ermöglicht.
Der Free Pascal Compiler bietet die Möglichkeit einzelne Bits im Speicher anzusprechen.
Mit dem Beispiel kann sowohl das ganze Byte als auch das einzelne Bit in diesem Byte angeprochen werden.
Dies kann man mit einem Record oder einem Array lösen.
...
// Compilerdirektive
{$BITPACKING ON}
...
type
TByteBits = bitpacked record
Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7: Boolean;
end;
TByteEx = packed record
case Integer of
0: (ByteAccess: Byte);
1: (BitAccess: TByteBits);
3: (BitArray: bitpacked array[0..7] of Boolean);
end;
...
Beispiel für die Verwendung von TByteBits und TByteEx:
// Wertzuweisung als Byte
ByteEx.ByteAccess := 4;
// Ändert den Wert von Bit7 und damit den Wert
// der über ByteEx.ByteAccess wieder ausgelesen wird
// in diesem Beispiel beträgt der Wert in
// ByteEx.ByteAccess 132
ByteEx.BitAccess.Bit7 := True;
// Über die Array
ByteEx.BitArray[7] := True;
Set
In Sets kann man die Bits eintragen, die für die Bitmanipulation in frage kommen.
...
// Compilerdirektiven
{$packset 1}
{$packenum 1}
...
type
TSetByteBits = set of (Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7);
...
var
SetByteBits: TSetByteBits;
...
begin
...
// legt fest, welche Elemente im Set gespeichert werden
SetByteBits := [Bit0 .. Bit7];
// Startet eine Bitmanipulation, wenn Bit3 im Set gefunden wird
if Bit3 in SetByteBits then
begin
...
end;
...
end;
...
TBits
Diese Klasse ist Teil der Klasse Unit aus der Free Pascal RTL Bibliothek. Die Klasse bietet einige Methoden zur Bit-Manipulation.
TBits = class(TObject)
public
constructor Create(TheSize : longint = 0); virtual;
destructor Destroy; override;
function GetFSize : longint;
procedure SetOn(Bit : longint);
procedure Clear(Bit : longint);
procedure Clearall;
procedure AndBits(BitSet : TBits);
procedure OrBits(BitSet : TBits);
procedure XorBits(BitSet : TBits);
procedure NotBits(BitSet : TBits);
function Get(Bit : longint) : boolean;
procedure Grow(NBit : longint);
function Equals(Obj : TObject): Boolean; override; overload;
function Equals(BitSet : TBits) : Boolean; overload;
procedure SetIndex(Index : longint);
function FindFirstBit(State : boolean) : longint;
function FindNextBit : longint;
function FindPrevBit : longint;
// Funktionen und Eigenschaften zu entsprechen TBits class
function OpenBit: longint;
property Bits[Bit: longint]: Boolean read get write SetBit; default;
property Size: longint read FBSize write setSize;
end;
Beispiel für eine Verwendung:
...
var
Bits: TBits;
bytI: Byte;
begin
...
// Erstellt das Objekt
Bits := TBits.Create;
// Legt die Grösse fest
Bits.Size := 5;
// legt für einige Bits den Wert fest
Bits[0] := true;
Bits[1] := true;
Bits[4] := true;
// Ausagbe der Werte
for bytI := 0 to Bits.Size-1 do
if Bits[bytI] = true
then ShowMessage(inttostr(bytI) + ' ' + BoolToStr(Bits[bytI]))
else ShowMessage(inttostr(bytI) + ' ' + BoolToStr(Bits[bytI]));
// gibt den Speicher des Objektes wieder frei
Bits.Free;
...
end;
...
Record Eigenschaften und Wertindex
Another interesting implementation of bit aligned structure can be used with capabilities of advanced records (FPC 2.6.0+). For all properties you have to use setter and getter which can handle general bit manipulations and set index which is passed to these methods. For more information refer to Indexed properties. Because index is only one, it has to be divided to two parameters to describe location and size on bit value. In case of the following example, the offset can be 0..255 and size of value 0..255 bits. Another problem is that you have to ensure that defined structure components will not overlay.
{$mode delphi}
TSomeBitStructure = record
private
RawData: Word;
function GetBits(const AIndex: Integer): Integer; inline;
procedure SetBits(const AIndex: Integer; const AValue: Integer); inline;
public
// High byte of index offset, low byte of index is bit count
property OneBit: Integer index $0001 read GetBits write SetBits;
property TwoBits: Integer index $0102 read GetBits write SetBits;
property FourBits: Integer index $0304 read GetBits write SetBits;
property EightBits: Integer index $0708 read GetBits write SetBits;
end;
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
function TSomeBitStructure.GetBits(const AIndex: Integer): Integer;
var
Offset: Integer;
BitCount: Integer;
Mask: Integer;
begin
BitCount := AIndex and $FF;
Offset := AIndex shr 8;
Mask := ((1 shl BitCount) - 1);
Result := (RawData shr Offset) and Mask;
end;
procedure TSomeBitStructure.SetBits(const AIndex: Integer; const AValue: Integer);
var
Offset: Integer;
BitCount: Integer;
Mask: Integer;
begin
BitCount := AIndex and $FF;
Offset := AIndex shr 8;
Mask := ((1 shl BitCount) - 1);
Assert(aValue <= Mask);
RawData := (RawData and (not (Mask shl Offset))) or (AValue shl Offset);
end;