tags:

views:

153

answers:

5
  • In other languages like C++, you have to keep track of the array length yourself - how does Delphi know the length of my array? Is there an internal, hidden integer?

  • Is it better, for performance-critical parts, to not use Length() but a direct integer managed by me?

A: 

Is there an internal, hidden integer

Yes.

to not use Length() but a direct integer managed by me?

Doesn't matter.

See Dynamic arrays item in Addressing pointers article by Rudy Velthuis.

P.S. You can also hit F1 button.

Alexander
It **does** matter, as it wastes CPU cycles, memory and is error prone.
Ulrich Gerhardt
How is it error prone? I've never had trouble with Length() not working or returning the wrong value... how else would it be prone to errors?
David M
+4  A: 

Yes, there are in fact two additional fields with dynamic arrays. First is the number of elements in the array at -4 bytes offset to the first element, and at -8 bytes offset there's the reference count. See Rudy's article for a detailed explanation.

For the second question, you'd have to use SetLength for sizing dynamic arrays, so the internal 'length' field would be available anyway. I don't see much use for additional size tracking.

Sertac Akyuz
+16  A: 

There are three kinds of arrays, and Length works differently for each:

  • Dynamic arrays: These are implemented as pointers. The pointer points to the first array element, but "behind" that element (at a negative offset from the start of the array) are two extra integer values that represent the array's length and reference count. Length reads that value. This is the same as for the string type.

  • Static arrays: The compiler knows the length of the array, so Length is a compile-time constant.

  • Open arrays: The length of an open array parameter is passed as a separate parameter. The compiler knows where to find that parameter, so it replaces Length with that a read of that parameter's value.

Rob Kennedy
Some precision with the screen type: since Delphi 2009, there is a 3rd "extra integer", which codes the size (in byte) for every character in the string (i.e. 1 for AnsiString and 2 for UnicodeString) and the charset (used for AnsiString) - as two word aggregated as one integer. Since Delphi 2007, the length() is an inlined function reading the hidden length integer, which is very fast. So using length() is very fast, faster than using strlen (I emphazies this point, since you're coming from c/c++ world).
A. Bouchez
@A. Bouchez: In your first sentence: screen type == string type?
Ulrich Gerhardt
+2  A: 

Since Rob Kennedy gave such a good answer to the first part of your question, I'll just address the second one:

Is it better, for performance-critical parts, to not use Length() but a direct integer managed by me?

Absolutely not. First, as Rob mentioned, the compiler does it's thing to access the information extremely quickly, either by reading a fixed offset before the start of the array in the case of dynamic ones, using a compile-time constant in the case of static ones, and passing a hidden parameter in the case of open arrays, you're not going to gain any improvement in performance.

Secondly, the direct integer managed by you wouldn't be any faster, but would actually use more memory (an additional integer allocated along with the one Delphi already provides for dynamic and open arrays, and an extra integer entirely in the case of static arrays).

Even if you directly read the value Delphi stores already for dynamic arrays, you wouldn't gain any performance over Length(), and would risk your code breaking if the internal representation of that hidden header for arrays changes in the future.

Ken White
+5  A: 

Don't forget that the layout of dynamic arrays and the like would change in a 64-bit version of Delphi, so any code that relies on finding the length at a particular offset would break.

I advise just using Length(). If you're working with it in a loop, you might want to cache it, but don't forget that a for loop already caches the terminating bounds of the loop.

Barry Kelly