How is a set organized in memory in Delphi?
What I try to do is casting a simple type to a set type like
var
MyNumber : Word;
ShiftState : TShiftState;
begin
MyNumber:=42;
ShiftState:=TShiftState(MyNumber);
end;
Delphi (2009) won’t allow this and I don’t understand why. It would make my life a lot easier in cases where I get a number where single bits encode different enum values and I just could cast it like this. Can this be done?
One approach I was going to go for is:
var
ShiftState : TShiftState;
MyNumber : Word absolute ShiftState;
begin
MyNumber:=42;
end;
But before doing this I thought I’d ask for the memory layout. It’s more a feeling than knowlege what I am having right now about this.
A Delphi set is a bit field who’s bits correspond to the associated values of the elements in your set. For a set of normal enumerated types the bit layout is straight-forward:
Things get a bit interesting when you’re dealing with a non-contiguous set or with a set that doesn’t start at 0. You can do that using Delphi’s subrange type (example:
set of 3..7) or using enumerated types that specify the actual ordinal value for the elements:In such cases Delphi will allocate the minimum required amount of bytes that will include all required bits, but will not “shift” bit values to use less space. In the
EnumSetexample Delphi will use two bytes:seveneightelevenYou can see some tests I did over here: Delphi 2009 – Bug? Adding supposedly invalid values to a set
Tests were done using Delphi 2010, didn’t repeat them for Delphi XE.