转篇文章,对初学者对理解集合有一定帮助
[转]
集合类型中的存储方式...
作者:zswangII
procedure TfrmMain.FormCreate(Sender: TObject);
mysql type
myset = set of 1..30;
var
testset: myset;
begin
testset := [1,6,11,5,12,31];
if 31 in testset then
ShowMessage('31 in testset!');
end;
照书上的说31这个元素已经超出了myset集合允许的范围,但测试的结果是程序还是弹出了对话框显示'31 in testset!',请问这是为什么?
---------------------------------------------------------------
这是由于集合的存储方式产生的现象~~
要了解这个问题先要分析集合类型在内存中是如何存储的~~
来一步一步测试看~~
(*例子1*)
type
TSetTest = set of 0..7;
var
S: TSetTest;
begin
S := [0, 1, 3];
Memo1.Lines.Values['SizeOf(S)'] := IntToStr(SizeOf(S));
Memo1.Lines.Values['S'] := IntToHex(Byte(S), 0);
end;
-------Memo1.Text-------
SizeOf(S)=1 //这说明0..7的集合占用了一个字节~~
S=B //二进制(0000 1011) 说明一个字位表示一个元素是否存在~~
-------------7654 3210 //0, 1, 3存在~~
(*例子2*)
type
TSetTest = set of 0..8;
var
S: TSetTest;
begin
S := [0, 1, 3];
Memo1.Lines.Values['SizeOf(S)'] := IntToStr(SizeOf(S));
Memo1.Lines.Values['S'] := IntToHex(Byte(S), 0);
end;
-------Memo1.Text-------
SizeOf(S)=2 //目前有9个元素,按照一个字位存放一个元素,可以推论:一个集合的大小等于该集合元素总数 div 8+ 1~~
S=B //二进制(0000 0000 |0000 1011) 这里看以看出还有7个字位是空余的~~
-------------5432 1098 7654 3210 //0, 1, 3存在~~
(*例子2*)
procedure TForm1.Button2Click(Sender: TObject);
type
TSetTest = set of 7..8;
var
S: TSetTest;
begin
S := [0, 1, 3];
Memo1.Lines.Values['SizeOf(S)'] := IntToStr(SizeOf(S));
Memo1.Lines.Values['S'] := IntToHex(Word(S), 0);
end;
-------Memo1.Text-------
SizeOf(S)=2 //按照上面的推论,7..8只有两个元素,占用1个字节(2 div 8 + 1=1),可实际是2个字节,因为集合存储起始元素的序号只能是0、8、16……等2的次方数,估计是为了提高运算效率~~
S=B //二进制(0000 0000 |0000 1011)
-------------5432 1098 7654 3210 //0, 1, 3存在~~
从内存存储的角度去分析这个问题,就很简单了~~
---------------------------------------------------------------
这是DELPHI对集合的处理方式问题
---------------------------------------------------------------
DELPHI处理时,采用字节位进行处理
比如1,63,128等都是一个点位,
如果你用1..30那么就可以处理到63的数字
[此贴子已经被作者于2007-4-16 19:07:54编辑过]