Solved

How can I store values of different types (double, short string) in a dynamic byte array using array index numbers?

Posted on 2003-11-22
7
396 Views
Last Modified: 2010-04-05
How can I store values of different types (double, short string) in a dynamic byte array using array index numbers?

I know it can be done with a static array.
Using a dynamic array, the problem may be how to have the index point to the right memory address...

Thank you for your time and attention!

// Example using a static array (works fine)
program staticarray;
{$APPTYPE CONSOLE}
uses SysUtils;
var
  A : array[0..23] of byte;
  aDouble: double;
  aString: string;
  s : string;
begin
  aDouble:= 2.349;
  pdouble(@A)^ := aDouble;      // store a double in the first eight bytes (0-7) of array A

  aString := 'abcd';
  pstring(@A[8])^ := aString;  // store a 4-byte string in bytes 8-11 of array A

  aDouble:= 1.0552;
  pdouble(@A[12])^ := aDouble;   // store a double in bytes 12-19 of array A

  aString := 'cdef';
  pstring(@A[20])^ := aString;   // store the string in bytes 20-23 of array A

  s :=         floattostr(pdouble(@A)^)      // retrieve the values from the byte array
       + #10 + pstring(@A[8])^
       + #10 + floattostr(pdouble(@A[12])^)
       + #10 + pstring(@A[20])^;
  writeln(#10+s);
end.

// Same example using a dynamic array (crashes)
program dynamicarray;
{$APPTYPE CONSOLE}
uses SysUtils;
var
  A : array of byte;
  aDouble: double;
  aString: string;
  s : string;
begin
  setlength(A,24);

  aDouble:= 2.349;
  pdouble(@A)^ := aDouble;      // store a double in the first eight bytes (0-7) of array A

  aString := 'abcd';
  pstring(@A[8])^ := aString;  // store a 4-byte string in bytes 8-11 of array A

  aDouble:= 1.0552;
  pdouble(@A[12])^ := aDouble;   // store a double in bytes 12-19 of array A

  aString := 'cdef';
  pstring(@A[20])^ := aString;   // store the string in bytes 20-23 of array A

  s :=         floattostr(pdouble(@A)^)      // retrieve the values from the byte array
       + #10 + pstring(@A[8])^
       + #10 + floattostr(pdouble(@A[12])^)
       + #10 + pstring(@A[20])^;
  writeln(#10+s);
end.
0
Comment
Question by:KAsselberghs
  • 4
  • 2
7 Comments
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 9802765
How about using TVariant?
0
 

Author Comment

by:KAsselberghs
ID: 9804373
Yes, I consider(ed) using a variant data type, but I would like to avoid the overhead of extra memory usage (and speed decrease). Using a variant array might more than double memory usage.

My array may have to store up to 100's of doubles and short strings (strings up to 255 bytes in length), and the application I use it in may need many thousands of these arrays to read in all data. That's why I strive for a lean solution.

A byte array seems to me the most memory-efficient solution, but I will have to be able to fill it and retrieve values from it using type casts and array indices.
If this is possible with a static array, why not with a dynamic array?
Or am I looking for something that is just not possible in Delphi?

Thanks for your reaction,

Karel Asselberghs
0
 
LVL 33

Expert Comment

by:Slick812
ID: 9804436
in dynamic arrays the Pointer for the Array variable is NOT the pointer to the array's data as it is in a static array, I have used the First Member of the dynamic array as the Pointer to the Data for a dynamic array

pdouble(@A[0])^ := aDouble;


0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 33

Expert Comment

by:Slick812
ID: 9804460
and a warning. . . each time you change the length of a dymamic array, it will have a different memory address, this is why the variable pointer is NOT to the data of a dynamic array, the different memory location should not be a problem if you change array length, unless you use an address as a reference and then change the array length, in which case, the pointer reference made before the length change will be invalid
0
 
LVL 33

Accepted Solution

by:
Slick812 earned 500 total points
ID: 9804706
you might consider using your own Pointers, instead of a dymanic array for your code? Using your own pointers allows you to have a little more controll of what you do, but may not give you any advantage, depending on your code and what you might be doing, , ,
the following code uses a PByteArray to do what you do in your code . . . ..

procedure whatever;
var
pMemoryBlock, newMB: PByteArray;
Ext1: Extended;
str1: String[18];
int1: Integer;
begin
str1 := 'Hello to you today';
GetMem(pMemoryBlock, 1024);
Ext1 := 123.321;
PExtended(@pMemoryBlock[0])^ := Ext1;
PShortString(@pMemoryBlock[10])^ := str1;
int1 := 33;
PInteger(@pMemoryBlock[29])^ := int1;
if PInteger(@pMemoryBlock[29])^ = 33 then
ShowMessage('int1 is equal');
GetMem(newMB, 2048); // setLength in dynamic array get's new memory
CopyMemory(newMB, pMemoryBlock, 1024); //put data in new memory block
FreeMem(pMemoryBlock); //free old block
pMemoryBlock := newMB; //get new pointer location into the original variable
if PShortString(@pMemoryBlock[10])^ = 'Hello to you today' then
ShowMessage('str1 is still equal');
FreeMem(pMemoryBlock); //be sure to free memory
end;


here I gete a new larger memory block, and copy yhe old data to new block and reassign the original variable to the New pointer
much like what setlength does for a dynamic array
0
 
LVL 33

Expert Comment

by:Slick812
ID: 9804734
you might use the delphi procedure
procedure ReallocMem(var P: Pointer; Size: Integer);
instead of

GetMem(newMB, 2048);
CopyMemory(newMB, pMemoryBlock, 1024);
FreeMem(pMemoryBlock);
pMemoryBlock := newMB;

that becomes

ReallocMem(pMemoryBlock, 2028);


however, I have had some problems if the memory block was more than about 3 Kilobytes? ?
0
 

Author Comment

by:KAsselberghs
ID: 9814865
Dear slick812,

Thank you very much for giving my question so much thought.

Your solution works fine!

By the way, the examples I tried with memory blocks larger than 3k worked ok.

Thank you!

Karel Asselberghs
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
automatically logging in via bde delphi 3 70
creating threads in delphi 1 82
Delphi inherited method 6 63
TEMBEDDEDWB how can i change its user agent ? 8 48
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, just open a new email message. In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
Hi friends,  in this video  I'll show you how new windows 10 user can learn the using of windows 10. Thank you.

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now