[next] [prev] [prev-tail] [tail] [up]

#### Ansistrings

Ansistrings are strings that have no length limit. They are reference counted and null terminated. Internally, an ansistring is treated as a pointer. This is all handled transparantly, i.e. they can be manipulated as a normal short string. Ansistrings can be defined using the predefined AnsiString type.

If the {$H} switch is on, then a string definition using the regular String keyword and that doesn’t contain a length specifier, will be regarded as an ansistring as well. If a length specifier is present, a short string will be used, regardless of the {$H} setting.

If the string is empty (''), then the internal pointer representation of the string pointer is Nil. If the string is not empty, then the pointer points to a structure in heap memory.

The internal representation as a pointer, and the automatic null-termination make it possible to typecast an ansistring to a pchar. If the string is empty (so the pointer is nil) then the compiler makes sure that the typecasted pchar will point to a null byte.

Assigning one ansistring to another doesn’t involve moving the actual string. A statement

       S2:=S1;

results in the reference count of S2 being decreased by one, The referece count of S1 is increased by one, and finally S1 (as a pointer) is copied to S2. This is a significant speed-up in the code.

If the reference count reaches zero, then the memory occupied by the string is deallocated automatically, so no memory leaks arise.

When an ansistring is declared, the Free Pascal compiler initially allocates just memory for a pointer, not more. This pointer is guaranteed to be nil, meaning that the string is initially empty. This is true for local and global ansistrings or anstrings that are part of a structure (arrays, records or objects).

This does introduce an overhead. For instance, declaring

     Var
       A : Array[1..100000] of string;

Will copy 100,000 times nil into A. When A goes out of scope, then the reference count of the 100,000 strings will be decreased by 1 for each of these strings. All this happens invisibly for the programmer, but when considering performance issues, this is important.

Memory will be allocated only when the string is assigned a value. If the string goes out of scope, then its reference count is automatically decreased by 1. If the reference count reaches zero, the memory reserved for the string is released.

If a value is assigned to a character of a string that has a reference count greater than 1, such as in the following statements:

       S:=T;  { reference count for S and T is now 2 }
       S[I]:='@';

then a copy of the string is created before the assignment. This is known as copy-on-write semantics.

The Length (527) function must be used to get the length of an ansistring.

To set the length of an ansistring, the SetLength (570) function must be used. Constant ansistrings have a reference count of -1 and are treated specially.

Ansistrings are converted to short strings by the compiler if needed, this means that the use of ansistrings and short strings can be mixed without problems.

Ansistrings can be typecasted to PChar or Pointer types:

     Var P : Pointer;
         PC : PChar;
         S : AnsiString;

     begin
       S :='This is an ansistring';
       PC:=Pchar(S);
       P :=Pointer(S);

There is a difference between the two typecasts. When an empty ansistring is typecasted to a pointer, the pointer wil be Nil. If an empty ansistring is typecasted to a PChar, then the result will be a pointer to a zero byte (an empty string).

The result of such a typecast must be used with care. In general, it is best to consider the result of such a typecast as read-only, i.e. suitable for passing to a procedure that needs a constant pchar argument.

It is therefore NOT advisable to typecast one of the following:

1. expressions.
2. strings that have reference count larger than 0. (call uniquestring to ensure a string has reference count 1)

[next] [prev] [prev-tail] [front] [up]