Delphi Const Array
Suppose we want to create three one-dimensional arrays for 50 members in our programming community. The first array is for names, the second for e-mails, and the third for number of uploads (components or applications) to our community.
Const array of xxx function parameters and records. Const Array of Record. Convert array of variant to array of const. Array of const vs. Variant Arrays. Var.sized const arrays? Array of const - problem in Delphi 3. Const arrays: how to assign values? Array of const. TStrings and array of const. CURE: Variable Array.
Each array (list) would have matching indexes and plenty of code to maintain all three lists in parallel. Of course, we could try with one three-dimensional array, but what about its type? We need string for names and e-mails, but an integer for the number of uploads.
The way to work with such a data structure is to use Delphi's record structure.
TMember = Record ..
For example, the following declaration creates a record type called TMember, the one we could use in our case.
Essentially, a record data structure can mix any of Delphi's built-in types including any types you have created. Record types define fixed collections of items of different types. Each item, or field, is like a variable, consisting of a name and a type.
TMember type contains three fields: a string value called Name (to hold the name of a member), a value of a string type called eMail (for one e-mail), and an integer (Cardinal) called Posts (to hold the number of submissions to our community).
Once we have set up the record type, we can declare a variable to be of type TMember. TMember is now just as good variable type for variables as any of Delphi's built-in types like String or Integer. Note: the TMember type declaration, does not allocate any memory for the Name, eMail, and Posts fields;
To actually create an instance of TMember record we have to declare a variable of TMember type, as in the following code:
Now, when we have a record, we use a dot to isolate the fields of DelphiGuide.
Note: the above piece of code could be rewritten with the use of withkeyword.
We can now copy the values of DelphiGuide’s fields to AMember.
Record Scope and Visibility
Record type declared within the declaration of a form (implementation section), function, or procedure has a scope limited to the block in which it is declared. If the record is declared in the interface section of a unit it has a scope that includes any other units or programs that use the unit where the declaration occurs. Bangla movie download sites.
An Array of Records
Since TMember acts like any other Object Pascal type, we can declare an array of record variables:
Note: Here's how to declare and initialize a constant array of records in Delphi.
Records as Record Fields
Since a record type is legitimate as any other Delphi type, we can have a field of a record be a record itself. For example, we could create ExpandedMember to keep track of what the member is submitting along with the member information.
Filling out all the information needed for a single record is now somehow harder. More periods (dots) are required to access the fields of TExpandedMember.
Record With 'Unknown' Fields
A record type can have a variant part (not to be confused with Variant type variable). Variant records are used, for example, when we want to create a record type that has fields for different kinds of data, but we know that we will never need to use all of the fields in a single record instance. To learn more about Variant parts in Records take a look at Delphi's help files. The use of a variant record type is not type-safe and is not a recommended programming practice, particularly for beginners.
However, variant records can be quite useful, if you ever find yourself in a situation to use them.
I have a few const arrays of the same base type but different sizes, and I need to point to them in the const records. The code below compiles successfully, but finishes with error.
In my code I need to access data from the cOffsetsA/B arrays having a pointer to the record. I tried to do it like this:
and this causes error - 'Access violation .. read of address 000000..'
Can anybody explain is wrong here and how to fix it, how should it be done?
Probably I will also have to add the _length field in the record, which will hold the size of the array the pointer is pointing to; this is not a problem.
Best regards,LUK
3 Answers
While the use of constants like this are okay in Delphi, I just want to add that it's in general not a very good idea to do things this way. Personally, if this code is in some unit, I would use something like this: (D2007 and higher)
Thus, the record gets a constructor which will fill it with the proper data. As a disadvantage, you can't declare it as a const anymore, if you want to use the constructor to fill it with data. However, you can solve this by using the following code in the Initialization section:
Delphi Initialize Dynamic Array
This code will declare the record as a global variable instead of constant, and fill it with your data.
Your constructor could look like this:
Delphi Const Array Function
Which will fill the record with your data. However, you don't have to use the constructor to create records this way! It's just an added function.
To make it even more interesting, you can add properties for the two points and array, making the fields themselves private and only declaring read method for the properties. This way, you can still make sure it's content is read-only and stays read-only.
But what's the risk of using your code? Well, since you declare them all as constants, there isn't much risk, unless you allow assignable typed constants. ({$J+} is declared..) In that case, a piece of code could change a value in cOffsetsA and it would also change in cRec1. Is that what you want?
Anyway, by using a constructor and by initializing them in code, you make your code more dynamic. However, it still continues to stay a simple record type and the additional properties and methods won't change it's structure or size.
You will need Delphi 2007 or better for this, though..
It looks like I found the answer myself:
is a dynamic array type and setLength must be used with any variable of this type to allocate the memory. What I need is a pointer to an existing constant array, so the only thing which must be changed in order to fix the problem is the declaration of this type. It should look like:
and yes, I have to add the _length field in the records as low(pMyRec^.aOffsets^), high(..) and length(..) do not work.
Best regards,LUK