原理性的东西欧一向很弱,看高人的回答
-------------------------转自网络
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1129029
咳,这个问题应该很容易的。不过还是说一下,省得你化这许多力气在这里。
TMessage = packed record
Msg: Cardinal; // 消息ID
case Integer of // 此处的Integer针对什么来说的?
0: ( // 什么时候用到?
WParam: Longint; // wparam 在MFC中是什么意思?
LParam: Longint; // lparam 在MFC中是什么意思?
Result: Longint);
1: ( // 什么时候用到?
WParamLo: Word;
WParamHi: Word;
LParamLo: Word;
LParamHi: Word;
ResultLo: Word;
ResultHi: Word);
end;
就是告诉编译器,TMessage这个数据类型是这样的:
00~03:Msg: Cardinal;
04~05:WParamLo: Word;--1
06~07:WParamHi: Word;--2; 1,2和起来是: WParam: Longint
08~09:LParamLo: Word;--3
0A~0B:LParamHi: Word;--4; 3,4和起来是: LParam: Longint
0C~0D:ResultLo: Word;--5
0E~0F:ResultHi: Word;--6; 5,6和起来是:Result: Longint
你即可以用WParamLo,WParamHi,LParamLo,LParamHi,ResultLo,ResultHi来访问04~0F的数据
也可以用WParam,LParam,Result来访问04~0F的数据。
你想怎么访问都可以。就是使你用起来更方便。
比如有一个记录:
type
MyRecord=Record
a:Integer;
Data:Integer
end;
比如,我想访问Data的高16位和低16位,就可以这样定义:
type
MyRecord2=Record
a:Integer;
case integer of
0
Data:Integer);
1
DataHi,DataLow:Word) ;
end;
其实,MyRecord2和MyRecord的内存使用是完全一样的,但你可以通过
DataHi,DataLow来访问Data的高16位和低16位。
具体的实现细节,我希望你自己去找吧!
DarwinZhang (2002-05-31 19:07:00)
综合上面的,不难给出:
TMessage2 = packed record
Msg: Cardinal;
WParam: Longint;
LParam: Longint;
Result: Longint;
end;
和TMessage在具体的物理内存上是一样的。
有的时候可能不一样,比如:
type
TestRec=Record
a:Byte;
case integer of
0
b:Integer);
1
c,d,e:Word);//多出一个e,内存就会强制加大
end;
TestRec2=Record
a:Byte;
b:Integer;
end;
TestRec和TestRec2就不相等。
--------------------------------------------------看帮助
A 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 form
fieldList1: 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).