Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Delphi Compiler - Mengen und Aufzählungstypen?? [INTERN] (https://www.delphipraxis.net/147999-delphi-compiler-mengen-und-aufzaehlungstypen-%5Bintern%5D.html)

olee 20. Feb 2010 13:23


Delphi Compiler - Mengen und Aufzählungstypen?? [INTERN]
 
Hi,

Ich habe ein kleines Problem (was könnts sonst sein :mrgreen:)

Ich möchte in mein RUTIS nun endlich Mengentypen implementieren:
Also z.B.
Delphi-Quellcode:
type
  TReplaceFlag = (rfReplaceAll, rfIgnoreCase);
  TReplaceFlags = set of TReplaceFlag;
DAs Problem ist, das ich mir nicht sicher bin, wie Delphi das verarbeitet.

Ich habe bisher folgendes festgestellt, bin mir aber bei all dem noch nicht so sicher:

Wenn man einen Aufzählungstyp hat wie TReplaceFlag, so ist der intern gespeicherte Wert für das erste Flag - also
Delphi-Quellcode:
const
  rfReplaceAll = 0;
  rfIgnoreCase = 1;
Wenn man dagegen ein Set hat, scheint es so als ob der das folgendermaßen macht:
Delphi-Quellcode:
var
  IstEnthalten_rfReplaceAll : Boolean;
  IstEnthalten_rfReplaceAll : Boolean;
begin
  IstEnthalten_rfReplaceAll := (round(IntPower(2, fIgnoreCase+1)) and ReplaceFlags) <> 0;
  IstEnthalten_rfIgnoreCase := (round(IntPower(2, fIgnoreCase+1)) and ReplaceFlags) <> 0;
Kann mir das jmd. bestätigen oder sonst noch etwas dazu beitragen?

MFG

himitsu 20. Feb 2010 13:34

Re: Delphi Compiler - Mengen und Aufzählungstypen?? [INTERN]
 
Bei Sets mit vorfefinierten werten, sowie bei Integersets, ist es nicht so eindeutig,

aber im Allgemeinen:

Delphi-Quellcode:
type e = (a, b, c, d);
  s = set of e;

// oder
type s = set of (a, b, c, d);
Werte sind alle durchnummeriert, von 0 beginnend
a=0, b=1, c=2 und d=3

das Set ist dann ein "Bit-Array" aller werte

Bit 0 = a
Bit 1 = b
Bit 2 = c
Bit 3 = d

ergibt also folgendes
bitmaskte = $1 shl Wert;

$0001 = a
$0002 = b
$0004 = c
$0008 = d
$0010 = ...


Hat das Set also einen wert von $0005, dann sind a und c gesetzt.
Delphi-Quellcode:
$0005 = (1 shl 0) {1} or (1 shl 2) {4}
Dann sind in Delphi die Sets so groß/klein wie nötig
- bis 8 Werte = Byte, bis 16 Werte = Word usw.

olee 20. Feb 2010 13:39

Re: Delphi Compiler - Mengen und Aufzählungstypen?? [INTERN]
 
Das mit dem shl hab ich mir auch schon gedacht ;)

Hatte es vorhin nur noch nicht geschrieben, weil ichs noch nachprüfen wollte.

Also ist das damit ja relativ leicht.

Aber wie sieht es aus mit der größe das Datentypes.

Also wenn so ein Set nur max 8 Eleente enthält - ist das dann nur ein Byte groß? und wie siehts aus wenns mehr enthält??

MFG

himitsu 20. Feb 2010 14:20

Re: Delphi Compiler - Mengen und Aufzählungstypen?? [INTERN]
 
1-8 = 1 Byte
9-16 = 2 Byte (Word)
17-32 = 4 Byte (LongWord)
33-64 = 8 Byte (UInt64)
und dann jeweils in 4 Byte-Schritten (glaub ich) bis 32 Byte = maximale 256 Werte

generic 20. Feb 2010 15:37

Re: Delphi Compiler - Mengen und Aufzählungstypen?? [INTERN]
 
Mit ord() kannst du die Position ermitteln.
Es gibt auch den Befehl
if (x in set) then

olee 20. Feb 2010 18:35

Re: Delphi Compiler - Mengen und Aufzählungstypen?? [INTERN]
 
Ich frage mich aber...

was wäre schneller im code?

Wenn ich jetzt intern das so mache, das ich mit dem Operator "in" arbeiten kann...

oder das manuell mache.

Also:
Delphi-Quellcode:
Result := (1 shl FlagID and Flags) <> 0;
EDIT: Wobei ich glaube 2. ist besser / einfacher ;)

EDIT 2:
Aber ich frage mich, wie ich das mit Sets mit mehr als 32 (bzw. 64) Elementen mache - also wenn ich den Operator and nicht mehr verwenden kann...

MFG

himitsu 20. Feb 2010 20:15

Re: Delphi Compiler - Mengen und Aufzählungstypen?? [INTERN]
 
Wie sieht denn deine Speicherverwaltung aus?
Bzw, wenn du auf reale SETs zugreifen willst, dann bleibt dann eh kein anderer Weg

abfragen:
Delphi-Quellcode:
if count <= 8 then result := ($1 shl value) and PByte(@data) <> 0
else if count <= 16 then result := ($1 shl value) and PWord(@data) <> 0
else result := ($1 shl (value mod 32)) and PLongWord(@data)[value div 32] <> 0;
   //result := ($1 shl (value and 31)) and PLongWord(@data)[value shr 5] <> 0;
OK, Byteweise ginge auch, auch wenn nicht unbedingt efektiv:
Delphi-Quellcode:
result := ($1 shl (value mod 8)) and PByte(@data)[value div 8] <> 0;
//result := ($1 shl (value and 7)) and PByte(@data)[value shr 3] <> 0;

entfernen (ohne "or i") und setzen (mit "or i"):
Delphi-Quellcode:
if count <= 8 then begin
  i := 1 shl value;
  PByte(@data) := (PByte(@data) and not i) or i;
end else if count <= 16 then begin
  i := 1 shl value;
  PWord(@data) := (PWord(@data) and not i) or i;
end else begin
  i := 1 shl (value mod 32);
  i2 := value div 32;
  PLongWord(@data)[i2] := (PLongWord(@data)[i2] and not i) or i;
  //i := 1 shl (value and 31);
  //i2 := value shr 5;
  //PLongWord(@data)[i2] := (PLongWord(@data)[i2] and not i) or i;
end;

Amateurprofi 20. Feb 2010 22:52

Re: Delphi Compiler - Mengen und Aufzählungstypen?? [INTERN]
 
Oder man macht das in Assembler

Sei EAX=@Data und EDX=count.

Delphi-Quellcode:
bt  [eax],edx // setzt CF=1 wenn das Bit count = 1 ist
bts [eax],edx // setzt CF=1 wenn das Bit count = 1 ist und setzt dann das Bit=1
btr [eax],edx // setzt CF=1 wenn das Bit count = 1 ist und setzt dann das Bit=0
btc [eax],edx // setzt CF=1 wenn das Bit count = 1 ist und "dreht es dann um"
Das schöne an diesen Befehlen ist, daß edx (also count) im Bereich −2^31 bis 2^31 − 1 sein darf.
Entsprechende Funktionen könnte man so gestalten:

Delphi-Quellcode:
FUNCTION IsBitSet(p:pointer; count:integer):Boolean;
asm
   bt [eax],edx
   setc al
end;

FUNCTION SetBit(p:pointer; count:integer):Boolean;
asm
   bts [eax],edx
   setc al
end;

FUNCTION ClearBit(p:pointer; count:integer):Boolean;
asm
   btr [eax],edx
   setc al
end;

FUNCTION ToggleBit(p:pointer; count:integer):Boolean;
asm
   btc [eax],edx
   setc al
end;

olee 21. Feb 2010 11:27

Re: Delphi Compiler - Mengen und Aufzählungstypen?? [INTERN]
 
@Amateurprofi:

Danke!

Diese ASM Funktionen sind genau das was ich brauchte.

Denn mir war schleierhaft, wie ich ein einzelntes Bit innerhalb eines Wertes mit einer Größe über 64 Bit abfragen konnte.

Ich werde das ganze dann mal ausprobieren. :coder2:

MFG


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:22 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz