TMessage = packed record
Msg: Cardinal;
case Integer of
0: (
WParam: Longint;
LParam: Longint;
Result: Longint);
1: (
WParamLo: Word;
WParamHi: Word;
LParamLo: Word;
LParamHi: Word;
ResultLo: Word;
ResultHi: Word);
end;
再定义这个结构中,我不明白case地用法在这里是什么意思,帮忙解释一下,谢谢
Msg: Cardinal;
case Integer of
0: (
WParam: Longint;
LParam: Longint;
Result: Longint);
1: (
WParamLo: Word;
WParamHi: Word;
LParamLo: Word;
LParamHi: Word;
ResultLo: Word;
ResultHi: Word);
end;
再定义这个结构中,我不明白case地用法在这里是什么意思,帮忙解释一下,谢谢
没有别的特殊的含义?
其中WParam为32bit 他由WParamLo 和WParamHi 组成(各16bit)
在引用时可以分别以32bit和16bit两种方法使用
Msg: Cardinal;
WheelDelta: Integer;
case Integer of
0: (
XPos: Smallint;
YPos: Smallint);
1: (
Pos: TSmallPoint;
Result: Longint);
end; TSmallPoint = packed record
x: SmallInt;
y: SmallInt;
end;
那这种结构呢,我就想知道case的这种用法给用户提供的借口是两个,但是编译器是怎么处理的呢?
Form1: TForm1;
msg:TMessage;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
msg.WParam:=100;
edit1.Text:=IntToStr(msg.WParamLo);
edit2.Text:=IntToStr(msg.WParamHi);
end;procedure TForm1.Button2Click(Sender: TObject);
begin
msg.WParamLo:=StrToInt(edit1.Text);
msg.WParamHi:=StrToInt(edit2.Text);
edit3.Text:=IntToStr(msg.WParam);
end;end.
--------------------
作了一个测试,意思好像就是相同分配的内存有两种访问方式把
感觉也没有太特别的...
type test=record
case boolean of
false:(ByteVar:byte);
true :(CharVar:char);
end;
var aTest:Test;
begin
aTest.ByteVar:=65;
memo1.Lines.Add('CharVar:'+aTest.CharVar);
aTest.CharVar:='a';
memo1.Lines.Add('ByteVar:'+inttostr(aTest.ByteVar)); memo1.Lines.Add('CharVar地址:'+inttostr(integer(@aTest.ByteVar)));
memo1.Lines.Add('ByteVar地址:'+inttostr(integer(@aTest.ByteVar)));
end;
/////我觉得它的发送形式都是一样的,主要是使用的时候可以用不同的解析方式吧???
WParam: Longint;
和
WParamLo: Word;
WParamHi: Word;
应该没有本质的区别的...
Msg: Cardinal;
WheelDelta: Integer;
case Integer of
0: (
XPos: Smallint;
YPos: Smallint);
1: (
Pos: TSmallPoint;
Result: Longint);
end; TSmallPoint = packed record
x: SmallInt;
y: SmallInt;
end;
那这种结构呢,我就想知道case的这种用法给用户提供的借口是两个,但是编译器是怎么处理的呢?
//////////////////////这种情况下,好像0/1的内存长度就不想等了,这个怎么办的那???
keyword: Variant parts in recordsA record type can have a variant part, which looks like a case statement. The variant part must follow the other fields in the record declaration.
To declare a record type with a variant part, use the following syntax.type recordTypeName = record fieldList1: type1;
...
fieldListn: typen;
case tag: ordinalType of
constantList1: (variant1);
...
constantListn: (variantn);
end;The first part of the declaration梪p to the reserved word case梚s the same as that of a standard record type. The remainder of the declaration梖rom case to the optional final semicolon梚s called the variant part. In the variant part,tag is optional and can be any valid identifier. If you omit tag, omit the colon (:) after it as well.
ordinalType denotes an ordinal type.
Each constantList is a constant denoting a value of type ordinalType, or a comma-delimited list of such constants. No value can be represented more than once in the combined constantLists.
Each variant is a comma-delimited list of declarations resembling the fieldList: type constructions in the main part of the record type. That is, a variant has the formfieldList1: type1; ...
fieldListn: typen;where each fieldList is a valid identifier or comma-delimited list of identifiers, each type denotes a type, and the final semicolon is optional. The types must not be long strings, dynamic arrays, variants (that is, Variant types), or interfaces, nor can they be structured types that contain long strings, dynamic arrays, variants, or interfaces; but they can be pointers to these types.Records with variant parts are complicated syntactically but deceptively simple semantically. The variant part of a record contains several
variants which share the same space in memory. You can read or write to any field of any variant at any time; but if you write to a field in one variant and then to a field in another variant, you may be overwriting your own data. The tag, if there is one, functions as an extra field (of type ordinalType) in the non-variant part of the record.Variant parts have two purposes. First, suppose you want to create a record type that has fields for different kinds of data, but you know that you will never need to use all of the fields in a single record instance. For example,type TEmployee = record
FirstName, LastName: string[40];
BirthDate: TDate;
case Salaried: Boolean of
True: (AnnualSalary: Currency);
False: (HourlyWage: Currency);
end;The idea here is that every employee has either a salary or an hourly wage, but not both. So when you create an instance of TEmployee, there is no reason to allocate enough memory for both fields. In this case, the only difference between the variants is in the field names, but the fields could just as easily have been of different types. Consider some more complicated examples:type TPerson = record
FirstName, LastName: string[40];
BirthDate: TDate;
case Citizen: Boolean of
True: (Birthplace: string[40]);
False: (Country: string[20];
EntryPort: string[20];
EntryDate, ExitDate: TDate);
end;type TShapeList = (Rectangle, Triangle, Circle, Ellipse, Other);
TFigure = record
case TShapeList of
Rectangle: (Height, Width: Real);
Triangle: (Side1, Side2, Angle: Real);
Circle: (Radius: Real);
Ellipse, Other: ();
end;For each record instance, the compiler allocates enough memory to hold all the fields in the largest variant. The optional tag and the constantLists (like Rectangle, Triangle, and so forth in the last example above) play no role in the way the compiler manages the fields; they are there only for the convenience of the programmer.
The second reason for variant parts is that they let you treat the same data as belonging to different types, even in cases where the compiler would not allow a typecast. For example, if you have a 64-bit Real as the first field in one variant and a 32-bit Integer as the first field in another, you can assign a value to the Real field and then read back the first 32 bits of it as the value of the Integer field (passing it, say, to a function that requires integer parameters).
TMSHMouseWheel = packed record
Msg: Cardinal; //4
WheelDelta: Integer; //4
case tag:Integer of //4 这个tag:可以缺省,不过加上去会多用去4个字节
0: (
XPos: Smallint; //2
YPos: Smallint); //2
1: (
Pos: TSmallPoint; //4
Result: Longint); //4
end; TSmallPoint = packed record
x: SmallInt;
y: SmallInt;
end;
var MSHMouseWheel:TMSHMouseWheel;
AnyVar:integer;
procedure TForm1.FormCreate(Sender: TObject);
begin
memo1.Lines.Add('MSHMouseWheel:'+inttostr(integer(@MSHMouseWheel)));
memo1.Lines.Add('Msg地址:'+inttostr(integer(@MSHMouseWheel.Msg)));
memo1.Lines.Add('WheelDelta地址:'+inttostr(integer(@MSHMouseWheel.WheelDelta)));
memo1.Lines.Add('tag地址:'+inttostr(integer(@MSHMouseWheel.tag)));
memo1.Lines.Add('XPos地址:'+inttostr(integer(@MSHMouseWheel.XPos)));
memo1.Lines.Add('YPos地址:'+inttostr(integer(@MSHMouseWheel.YPos)));
memo1.Lines.Add('Pos地址:'+inttostr(integer(@MSHMouseWheel.Pos)));
memo1.Lines.Add('Pos.x地址:'+inttostr(integer(@MSHMouseWheel.Pos.x)));
memo1.Lines.Add('Pos.y地址:'+inttostr(integer(@MSHMouseWheel.Pos.y)));
memo1.Lines.Add('Result地址:'+inttostr(integer(@MSHMouseWheel.Result)));
memo1.Lines.Add('SizeOfMSHMouseWheel:'+inttostr(SizeOf(MSHMouseWheel)));
memo1.Lines.Add('AnyVar地址:'+inttostr(integer(@AnyVar)));
//case integer是编译器预编译的,就是说在编译时就确定的变量的类型和地址,不需要在
//运行期去区分,只需要去调用 MSHMouseWheel.Pos.x 或者 MSHMouseWheel.XPos,他们的
//地址在运行期是不用去关心的 ,下面这样改变tag的值对这个结构的定义是没有任何影响的
pinteger(@MSHMouseWheel.tag)^:=1;
pinteger(@MSHMouseWheel.tag)^:=0;
end;