Pascal & Object Pascal DISCUSSION

What is the difference between ShortString, AnsiString and UnicodeString in Free Pascal and Delphi?

Started by mowafaq Pascal stringsShortStringAnsiStringUnicodeStringstring length byte
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

What is the difference between ShortString, AnsiString and UnicodeString in Free Pascal and Delphi?

mowafaq Pascal & Object Pascal Forum
#1

I am moving an old Turbo Pascal serial-port program to Lazarus, and later perhaps to Delphi. The old code uses s[0] to read the string length and declares fields as string[20]. In Free Pascal s[0] only compiles in some units, a long text gets cut at 255 characters in one place but not in another, and Length of a string containing a µ sign is one more than the number of characters I see.

What string types are actually behind the word string, and how are they stored?

Community replies 5

Re: What is the difference between ShortString, AnsiString and UnicodeString in Free Pascal and Delphi?

#2

The classic Pascal string, now called ShortString, is a fixed block of bytes in which element 0 holds the current length and the characters start at index 1. One length byte means a maximum of 255 characters. string[20] is a short string with capacity 20 and occupies 21 bytes; a plain ShortString occupies 256. It lives wherever the variable lives, on the stack or inside a record, with no heap allocation, and Length(s) is the same as Ord(s[0]).

Assigning a longer text silently truncates it, which is your cut at 255.

Re: What is the difference between ShortString, AnsiString and UnicodeString in Free Pascal and Delphi?

#3

The long string types are different in kind. An AnsiString variable is a single pointer, 4 or 8 bytes, to a heap block that holds a small header with a reference count and the length, followed by the characters and a terminating #0. The length is limited only by memory, Length is still a constant-time read of the header, and an empty string is a nil pointer.

Assignment copies the pointer and increments the count; the data is duplicated only when one of the owners modifies it (copy-on-write). There is no element 0, so s[0] does not compile; use Length and SetLength.

Re: What is the difference between ShortString, AnsiString and UnicodeString in Free Pascal and Delphi?

#4

What the word string means depends on the compiler and its settings. In Free Pascal it is ShortString in the {$H-} state and AnsiString under {$H+}. Lazarus puts {$mode objfpc}{$H+} at the top of new units, while a unit without that directive in the default mode gets short strings, which explains why your code behaves differently from one unit to the next. In Delphi 2009 and later, string is UnicodeString: the same reference-counted design, but with 2-byte UTF-16 elements.

Where a specific type matters, such as a record written to disk, name it explicitly instead of writing string.

Re: What is the difference between ShortString, AnsiString and UnicodeString in Free Pascal and Delphi?

#5

The µ puzzle is encoding. Lazarus keeps text in AnsiString as UTF-8, where µ takes two bytes, and Length counts elements, not characters: Length('10 µF') is 6 there. In Delphi the same literal has length 5, because µ is one UTF-16 code unit, but each element is 2 bytes, so the size in bytes is Length(s) * SizeOf(Char) = 10. Code such as Move(s[1], Buffer, Length(s)), written when a character was one byte, copies only half of the text in Delphi.

In Lazarus, UTF8Length from the LazUTF8 unit counts code points when you need that.

Re: What is the difference between ShortString, AnsiString and UnicodeString in Free Pascal and Delphi?

#6

For the serial-port part, do not keep binary protocol data in strings at all. Use array of Byte or TBytes for frames, and convert to text only what really is text. That avoids surprises from the encoding conversions the compiler inserts when assigning between string types with different code pages.

Short strings still have a place: string[20] in a packed record gives a fixed 21-byte field for file formats, and they need no heap, which suits small embedded targets. When calling C APIs, PChar(s) on a long string gives a pointer to the zero-terminated characters without copying.

TEP COMMUNITY