PDA

View Full Version : question about records



virtual
02-10-2010, 10:04 AM
hi all

i still don't understand this :

TColor =packed record
case integer of
0 : (R, G, B, A : Byte);
1 : (C : Cardinal);
end;

i mean 0 and 1 , whats the meaning of theme

vgo
02-10-2010, 10:26 AM
You can use the case statement to map different types of variables in the same memory space.The types used must be equal size, ie. Cardinal = 4 bytes in this case.



MyColor.R := $FF;
MyColor.G := $00;
MyColor.B := $FF;
MyColor.A := $00;
// Is equal to
MyColor.C := $00FF00FF;

Another example


TVector = record
case Integer of
0: (x, y, z: Single);
1: (v: array [0..2] of Single);
end;

MyVector.x := 5.75;
MyVector.y := 1.75;
MyVector.z := 0.00;
// Is equal to
MyVector.v[0] := 5.75;
MyVector.v[1] := 1.75;
MyVector.v[2] := 0.00;

chronozphere
02-10-2010, 02:14 PM
The 1 and 0 don't really mean anything. They just show that there are two different ways to access that piece of memory. During program execution, you can access either R, G, B and A or C to change the whole color at once. :)

WILL
02-10-2010, 09:10 PM
Yeah I found it funky that you can even stick functions and procedures into records as well.

Actually what I've never been able to figure out what 'packed' really does, or maybe I simply forgot. What is the purpose of this keyword and what does it do?

Brainer
02-10-2010, 09:15 PM
This is called a variant record. It's similar to C++'s union, but it's not the same, so you can't confuse them and put them two in the same basket. Compare Wikipedia article about unions (http://en.wikipedia.org/wiki/Union_%28computer_science%29) and variant records (http://en.wikipedia.org/wiki/Tagged_union).

Brainer
02-10-2010, 09:16 PM
@WILL: Look here ;) http://www.delphibasics.co.uk/RTL.asp?Name=Packed

WILL
02-10-2010, 09:38 PM
@WILL: Look here ;) http://www.delphibasics.co.uk/RTL.asp?Name=Packed
I see now. Thanks! :)

farcodev
02-10-2010, 09:52 PM
embedded case in a record is a very useful thing :)

virtual
03-10-2010, 07:53 AM
thank you so much

Bpascal
04-10-2010, 05:37 PM
I see now. Thanks! :)

About the "packed" clause in record defination, the most important think is to know is that if you do not use "packed" then delphi/pascal is free to add "invisibles" fields to the record to adjust the total size of the structure for best perfomance; so take note that using for example "sizeof(myrecord)," could give you a record size different at what you think if you sum indididually every field size;

Normaly there is not any problem using or not a packed record if you are going to use its members in traditional way. but if you are going to update/read data from records using move(), or blockread()/blockwrite() or similar function & procedure where you pass the record for read or write his members from a block memory then is adviced to use packed records so you as programmer are completly sure you record is aligned as you defined.

phibermon
15-10-2010, 06:38 PM
Interesting! I wonder what other complexities could arise from this. For example, if I were to serialize and stream a record from an architecture with different alignment, and pump the data directly into a record, would I get what I expected when querying the contents? My knowledge is lacking in this. When reading/writing various binary formats from/to a disk into/from records, I always set my record to be packed for fear of the byte alignment of an unpacked record resulting in unexpected values.

Can anyone tell me off the top of their heads if my fears are justified? I think some research is in order :)

EDIT : OK. from what I've read, you should not stream an unpacked, boundry aligned record to a file or across a network unless you can ensure that it will be read back or recieved with the same byte alignment. the padding of the record will get written too!

For streams/writing to a hard disk (or any other such bulk transfer of a record to some form of media) you should always use packed records! (unless you want to read that data on multiple architechures such as PowerPC, Arm etc, see 'endiness' below)

you should only use non packed records if they will only ever live in memory, at run time. And should do in this situation because of the performance improvments offered by byte aligned data.

In situations where you want the speed of byte aligned but still want to write that data out to a disk, it's highly advisable that you write it an element at a time, rather than just streaming from the address of the record using the size of the record.

If you are writing your code to run on architectures with different endiness you should never just stream a record, always break it down into it's component parts for endiness conversion!

I hope this has added to the discussion :)

chronozphere
15-10-2010, 06:52 PM
My guess is that byte alignment is determined by the compiler settings. You have to make sure that these are always the same for each program that is using your files containing the serialized records. I tend to leave these settings alone. :)

The case statement inside a record doesn't actually add any complexity AFAIK. It only gives you different ways to adress exactly the same memory.

phibermon
15-10-2010, 07:35 PM
Yes that is my understanding also. I believe there's another keyword called ABSOLUTE (http://www.delphigeist.com/2009/09/a...directive.html) that lets you do somthing similar to a variant record. A stated by Chronozphere, Variant records can be thought of two or more sets of variables that share the same memory. Absolute lets you do this as well, but directly for variables rather than in a record type.

(although I read that there's problems with this on architectures that force storage on the stack rather than allowing it to sit in a register. or the other way around, I forget)