Sign in Join
Wiki copytemporary

Character and string types: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Character and string types

OldNewLine
1+Free Pascal supports several **[[Char|character]] and [[String|string]] types**. They range from single ANSI characters to unicode strings and also include pointer types. Differences also apply to encodings and reference counting.
2+
3+## Character types
4+
5+### AnsiChar
6+
7+A variable of type **AnsiChar**, also referred to as **[[Char|char]]**, is exactly 1 byte in size, and contains one "ANSI" (local code page) character.
8+
9+| |
10+|-----|
11+| a |
12+
13+#### Reference
14+
15+- [FPC AnsiChar documentation](http://www.freepascal.org/docs-html/ref/refsu6.html)
16+- [[Char|Usage Char]]
17+- [Wikipedia:Windows code page#ANSI code page](https://en.wikipedia.org/wiki/Windows_code_page#ANSI_code_page)
18+
19+### WideChar
20+
21+A variable of type **WideChar**, also referred to as **UnicodeChar**, is exactly 2 bytes in size, and usually contains one [[LCL Unicode Support|Unicode]] code point (normally a character) in UTF-16 encoding. Note: it is impossible to encode all Unicode code points in 2 bytes. Therefore, 2 WideChars may be needed to encode a single code point.
22+
23+| | |
24+|-----|-----|
25+| | a |
26+
27+#### References
28+
29+- [FPC WideChar documentation](http://www.freepascal.org/docs-html/ref/refsu7.html)
30+- [UTF-16 information on Wikipedia](https://en.wikipedia.org/wiki/UTF-16)
31+- [[doc:rtl/system/unicodechar.html|RTL UnicodeChar documentation]]
32+
33+## Character-derived types
34+
35+### Array of Char
36+
37+Early Pascal implementations that were in use before 1978 did not support a string type (with the exception of string constants). The only possibility to store strings in variables was the use of arrays of char. This approach has many disadvantages and is no longer recommended. It is, however, still supported to ensure backward-compatibility with ancient code.
38+
39+#### Static Array of Char
40+
41+``` pascal
42+type
43+ TOldString4 = array[0..3] of char;
44+var
45+ aOldString4: TOldString4;
46+begin
47+ aOldString4[0] := 'a';
48+ aOldString4[1] := 'b';
49+ aOldString4[2] := 'c';
50+ aOldString4[3] := 'd';
51+end;
52+```
53+
54+The static array of char has now the content:
55+
56+| | | | |
57+|-----|-----|-----|-----|
58+| a | b | c | d |
59+
60+> **Note:** Unassigned chars can have any content, depending on what was just in memory when the memory for the array was made available.
61+
62+#### Dynamic Array of Char
63+
64+``` pascal
65+var
66+ aOldString: Array of Char;
67+begin
68+ SetLength(aOldString, 5);
69+ aOldString[0] := 'a';
70+ aOldString[1] := 'b';
71+ aOldString[2] := 'c';
72+ aOldString[3] := 'd';
73+end;
74+```
75+
76+The dynamic array of char has now the content:
77+
78+| | | | | |
79+|-----|-----|-----|-----|-----|
80+| a | b | c | d | \#0 |
81+
82+> **Note:** Unassigned chars in dynamic arrays have a content \#0, cause empty positions of all dynamic arrays are initially initialised with 0 (or \#0, or nil, or ...)
83+
84+### PChar
85+
86+A variable of type **[[PChar]]** is basically a pointer to a **Char** type, but allows additional operations. PChars can be used to access C-style [null-terminated strings](http://en.wikipedia.org/wiki/Null-terminated_string), e.g. in interaction with certain OS libraries or third-party software.
87+
88+| | | | |
89+|-----|-----|-----|-----|
90+| a | b | c | \#0 |
91+| ^ | | | |
92+
93+#### Reference
94+
95+- [FPC PChar documentation](http://www.freepascal.org/docs-html/ref/refsu12.html)
96+- [[doc:rtl/sysutils/pcharfunctions.html|PChar related functions]]
97+
98+### PWideChar
99+
100+A variable of type **PWideChar** is a pointer to a WideChar variable.
101+
102+| | | | | | | | |
103+|-----|-----|-----|-----|-----|-----|-----|-----|
104+| | a | | b | | c | \#0 | \#0 |
105+| ^ | | | | | | | |
106+
107+#### Reference
108+
109+- [[doc:rtl/system/pwidechar.html|RTL PWideChar documentation]]
110+
111+## String types
112+
113+### String
114+
115+The type **String** may refer to **ShortString** or **AnsiString**, depending from the [{\$H} switch](http://www.freepascal.org/docs-html/prog/progsu25.html#x32-310001.2.25). If the switch is off ({\$H-}) then any string declaration will define a **ShortString**. It size will be 255 chars, if not otherwise specified. If it is on ({\$H+}) **string** without length specifier will define an **AnsiString**, otherwise a **ShortString** with specified length. In **mode delphiunicode** **String'' is**UnicodeString'''.
116+
117+#### Reference
118+
119+- [[String|Usage String]].
120+- [[doc:rtl/sysutils/stringfunctions.html|String functions]]
121+- [[doc:rtl/strutils/index-5.html|Reference for unit 'strutils': Procedures and functions]]
122+
123+### ShortString
124+
125+Short strings have a maximum length of 255 characters with the implicit [[FPC Unicode support|codepage]] CP_ACP. The length is stored in the character at index 0. A short string of 255 characters uses 256 bytes of memory (one byte for the length specification and 255 bytes for characters).
126+
127+| | | | |
128+|-----|-----|-----|-----|
129+| \#3 | a | b | c |
130+
131+#### Reference
132+
133+- [FPC Single-byte String types documentation](https://www.freepascal.org/docs-html/ref/refsu9.html)
134+
135+### AnsiString
136+
137+Ansistrings are strings that have no length limit. They are [reference counted](http://en.wikipedia.org/wiki/Reference_counting) and are guaranteed to be [null terminated](http://en.wikipedia.org/wiki/Null-terminated_string). Internally, a variable of type **AnsiString** is treated as a pointer: the actual content of the string is stored on the heap, as much memory as needed to store the string content is allocated.
138+
139+<table>
140+<tbody>
141+<tr>
142+<td style="width: 8%;"></td>
143+<td style="width: 8%;"></td>
144+<td style="width: 8%;"></td>
145+<td style="width: 8%;"></td>
146+<td style="width: 8%;"></td>
147+<td style="width: 8%;"></td>
148+<td style="width: 8%;"></td>
149+<td style="width: 8%;"></td>
150+<td style="width: 8%;">a</td>
151+<td style="width: 8%;">b</td>
152+<td style="width: 8%;">c</td>
153+<td style="width: 8%;">#0</td>
154+</tr>
155+<tr>
156+<td colspan="4" style="width: 16%;">RefCount</td>
157+<td colspan="4" style="width: 16%;">Length</td>
158+<td></td>
159+<td></td>
160+<td></td>
161+<td></td>
162+</tr>
163+</tbody>
164+</table>
165+
166+On 64-bit targets, fields RefCount/Length consume 8 bytes each, not 4.
167+
168+An AnsiString type may also have a compile-time code page since FPC 2.7.1; a missing value defaults to `DefaultSystemCodePage`. A value of `CP_NONE` results in **`RawBytestring`** and a value of `CP_UTF8` results in **`UTF8String`**.
169+
170+#### Reference
171+
172+- [FPC Single-byte String types documentation](https://www.freepascal.org/docs-html/ref/refsu9.html)
173+
174+### UnicodeString
175+
176+Like **AnsiStrings**, **UnicodeStrings** are reference counted, null-terminated arrays, but they are implemented as arrays of **WideChars** instead of regular **Chars**.
177+
178+> **Note:** The UnicodeString naming is a bit ambiguous but probably due to its use in Delphi on Windows, where the OS uses UTF16 encoding; it's not the only string type that can hold Unicode string data (see also UTF8String)...
179+
180+<table>
181+<tbody>
182+<tr>
183+<td style="width: 7%;"></td>
184+<td style="width: 7%;"></td>
185+<td style="width: 7%;"></td>
186+<td style="width: 7%;"></td>
187+<td style="width: 7%;"></td>
188+<td style="width: 7%;"></td>
189+<td style="width: 7%;"></td>
190+<td style="width: 7%;"></td>
191+<td style="width: 7%;"></td>
192+<td style="width: 7%;">a</td>
193+<td style="width: 7%;"></td>
194+<td style="width: 7%;">b</td>
195+<td style="width: 7%;"></td>
196+<td style="width: 7%;">c</td>
197+<td style="width: 7%;">#0</td>
198+<td style="width: 7%;">#0</td>
199+</tr>
200+<tr>
201+<td colspan="4" style="width: 16%;">RefCount</td>
202+<td colspan="4" style="width: 16%;">Length</td>
203+<td></td>
204+<td></td>
205+<td></td>
206+<td></td>
207+<td></td>
208+<td></td>
209+<td></td>
210+<td></td>
211+</tr>
212+</tbody>
213+</table>
214+
215+On 64-bit targets, fields RefCount/Length consume 8 bytes each, not 4.
216+
217+#### Reference
218+
219+- [FPC Multi-byte String types documentation](http://www.freepascal.org/docs-html/ref/refsu10.html)
220+
221+### UTF8String
222+
223+In FPC 2.6.5 and below the type **UTF8String** was an alias to the type **AnsiString**. In FPC 2.7.1 and above it is defined as `UTF8String = type AnsiString(CP_UTF8);`
224+
225+It is meant to contain UTF-8 encoded strings (i.e. unicode data) ranging from 1..4 bytes per character. Note that **String** can also contain UTF-8 encoded characters.
226+
227+#### Reference
228+
229+- [FPC UTF8String documentation](https://www.freepascal.org/docs-html/ref/refsu9.html#x32-400003.2.4)
230+
231+### UTF16String
232+
233+The type **UTF16String** is an alias to the type **WideString**. In the LCL unit *lclproc* it is an alias to **UnicodeString**.
234+
235+#### Reference
236+
237+- [[doc:lcl/lclproc/utf16string.html|LCL UTF16String documentation]]
238+
239+### WideString
240+
241+Variables of type **[[Widestrings|WideString]]** (used to represent unicode character strings in COM applications) resemble those of type **UnicodeString**, but unlike them they are not reference-counted. On Windows they are allocated with a special windows function which allows them to be used for OLE automation.
242+
243+WideStrings consist of COM compatible UTF16 encoded bytes on Windows machines (UCS2 on Windows 2000), and they are encoded as plain UTF16 on Linux, Mac OS X and iOS.
244+
245+<table>
246+<tbody>
247+<tr>
248+<td style="width: 8%;"></td>
249+<td style="width: 8%;"></td>
250+<td style="width: 8%;"></td>
251+<td style="width: 8%;"></td>
252+<td style="width: 8%;"></td>
253+<td style="width: 8%;">a</td>
254+<td style="width: 8%;"></td>
255+<td style="width: 8%;">b</td>
256+<td style="width: 8%;"></td>
257+<td style="width: 8%;">c</td>
258+<td style="width: 8%;">#0</td>
259+<td style="width: 8%;">#0</td>
260+</tr>
261+<tr>
262+<td colspan="4" style="width: 16%;">Length</td>
263+<td></td>
264+<td></td>
265+<td></td>
266+<td></td>
267+<td></td>
268+<td></td>
269+<td></td>
270+<td></td>
271+</tr>
272+</tbody>
273+</table>
274+
275+#### Reference
276+
277+- [FPC Multi-byte String types documentation](http://www.freepascal.org/docs-html/ref/refsu10.html)
278+
279+## String-derived types
280+
281+### PShortString
282+
283+A variable of type **PShortString** is a pointer that points to the first byte of a **ShortString**-type variable (which defines the length of the ShortString).
284+
285+| | | | |
286+|-----|-----|-----|-----|
287+| \#3 | a | b | c |
288+| ^ | | | |
289+
290+#### Reference
291+
292+- [[doc:rtl/system/pshortstring.html|RTL PShortString documentation]]
293+
294+### PAnsiString
295+
296+Variables of type **PAnsiString** are pointers to **AnsiString**-type variables. However, unlike **PShortString**-type variables they don't point to the first byte of the header, but to the first **char** of the **AnsiString**.
297+
298+<table>
299+<tbody>
300+<tr>
301+<td style="width: 8%;"></td>
302+<td style="width: 8%;"></td>
303+<td style="width: 8%;"></td>
304+<td style="width: 8%;"></td>
305+<td style="width: 8%;"></td>
306+<td style="width: 8%;"></td>
307+<td style="width: 8%;"></td>
308+<td style="width: 8%;"></td>
309+<td style="width: 8%;">a</td>
310+<td style="width: 8%;">b</td>
311+<td style="width: 8%;">c</td>
312+<td style="width: 8%;">#0</td>
313+</tr>
314+<tr>
315+<td colspan="4" style="width: 16%;">RefCount</td>
316+<td colspan="4" style="width: 16%;">Length</td>
317+<td style="width: 8%;">^</td>
318+<td></td>
319+<td></td>
320+<td></td>
321+</tr>
322+</tbody>
323+</table>
324+
325+#### Reference
326+
327+- [[doc:rtl/system/pansistring.html|RTL PAnsiString documentation]]
328+
329+### PUnicodeString
330+
331+Variables of type **PUnicodeString** are pointers to variables of type **UnicodeString**.
332+
333+<table>
334+<tbody>
335+<tr>
336+<td style="width: 7%;"></td>
337+<td style="width: 7%;"></td>
338+<td style="width: 7%;"></td>
339+<td style="width: 7%;"></td>
340+<td style="width: 7%;"></td>
341+<td style="width: 7%;"></td>
342+<td style="width: 7%;"></td>
343+<td style="width: 7%;"></td>
344+<td style="width: 7%;"></td>
345+<td style="width: 7%;">a</td>
346+<td style="width: 7%;"></td>
347+<td style="width: 7%;">b</td>
348+<td style="width: 7%;"></td>
349+<td style="width: 7%;">c</td>
350+<td style="width: 7%;">#0</td>
351+<td style="width: 7%;">#0</td>
352+</tr>
353+<tr>
354+<td colspan="4" style="width: 16%;">RefCount</td>
355+<td colspan="4" style="width: 16%;">Length</td>
356+<td style="width: 7%;">^</td>
357+<td></td>
358+<td></td>
359+<td></td>
360+<td></td>
361+<td></td>
362+<td></td>
363+<td></td>
364+</tr>
365+</tbody>
366+</table>
367+
368+#### Reference
369+
370+- [[doc:rtl/system/punicodestring.html|RTL PUnicodeString documentation]]
371+
372+### PWideString
373+
374+Variables of type **PWideString** are pointers. They point to the first char of a **WideString**-typed variable.
375+
376+<table>
377+<tbody>
378+<tr>
379+<td style="width: 8%;"></td>
380+<td style="width: 8%;"></td>
381+<td style="width: 8%;"></td>
382+<td style="width: 8%;"></td>
383+<td style="width: 8%;"></td>
384+<td style="width: 8%;">a</td>
385+<td style="width: 8%;"></td>
386+<td style="width: 8%;">b</td>
387+<td style="width: 8%;"></td>
388+<td style="width: 8%;">c</td>
389+<td style="width: 8%;">#0</td>
390+<td style="width: 8%;">#0</td>
391+</tr>
392+<tr>
393+<td colspan="4" style="width: 16%;">Length</td>
394+<td style="width: 8%;">^</td>
395+<td></td>
396+<td></td>
397+<td></td>
398+<td></td>
399+<td></td>
400+<td></td>
401+<td></td>
402+</tr>
403+</tbody>
404+</table>
405+
406+#### Reference
407+
408+- [[doc:rtl/system/pwidestring.html|RTL PWideString documentation]]
409+
410+## String constants
411+
412+If you use only English (ASCII) constants your strings work the same with all types, on all platforms and all compiler versions. Non English strings can be loaded via resourcestrings or from files. If you want to use non English strings in code then you should read further.
413+
414+There are various encodings for non English strings. By default Lazarus saves Pascal files as **UTF-8 without BOM**. UTF-8 supports the full Unicode range. That means all string constants are stored in UTF-8. Lazarus also supports to change the encoding of a file to other encoding, for example under Windows your local codepage. The Windows codepage is limited to your current language group.
415+
416+| String Type, UTF-8 Source | With `{$codepage utf8}`? | FPC ≤ 2.6.5 | FPC ≥ 2.7.1 | FPC ≤ 2.7.1, [[Unicode Support in Lazarus|UTF8 as default CodePage]] |
417+|----|----|----|----|----|
418+| <tt>AnAnsiString:='ãü'; | No | Needs UTF8ToAnsi in RTL/WinAPI. Ok in LCL | Needs UTF8ToAnsi in RTL/WinAPI. Ok in LCL | Ok in RTL/W-WinAPI/LCL. Needs UTF8ToWinCP in A-WinAPI. |
419+| <tt>AnAnsiString:='ãü'; | Yes | System cp ok in RTL/WinAPI. Needs SysToUTF8 in LCL | Ok in RTL/WinAPI/LCL. Mixing causes conversion. | Ok in RTL/W-WinAPI/LCL. Needs UTF8ToWinCP in A-WinAPI |
420+| <tt>AnUnicodeString:='ãü'; | No | Wrong everywhere | Wrong everywhere | Wrong everywhere |
421+| <tt>AnUnicodeString:='ãü'; | Yes | System cp ok in RTL/WinAPI. Needs UTF8Encode in LCL | Ok in RTL/WinAPI/LCL.Mixing causes conversion. | Ok in RTL/W-WinAPI/LCL. Needs UTF8ToWinCP in A-WinAPI |
422+| <tt>AnUTF8String:='ãü'; | No | Same as AnsiString | Wrong everywhere | Wrong everywhere |
423+| <tt>AnUTF8String:='ãü'; | Yes | Same as AnsiString | Ok in RTL/WinAPI/LCL. Mixing causes conversion. | Ok in RTL/W-WinAPI/LCL. Needs UTF8ToWinCP in A-WinAPI. |
424+
425+- W-WinAPI = Windows API "W" functions, UTF-16
426+- A-WinAPI = Windows API non "W" functions, 8bit system ("ANSI") code page
427+- System CP = The 8bit system code page of the OS. For example code page [1252](http://en.wikipedia.org/wiki/Windows-1252).
428+
429+``` pascal
430+const
431+ c='ãü';
432+ cstring: string = 'ãü'; // see AnAnsiString:='ãü';
433+var
434+ s: string;
435+ u: UnicodeString;
436+begin
437+ s:=c; // same as s:='ãü';
438+ s:=cstring; // does not change encoding
439+ u:=c; // same as u:='ãü';
440+ u:=cstring; // fpc 2.6.1: converts from system cp to UTF-16, fpc 2.7.1+: depends on encoding of cstring
441+end;
442+```
443+
444+The rules for conversion are laid out in a ["Code page conversions"](https://freepascal.org/docs-html/ref/refsu9.html#x32-380003.2.4) section in the FPC manual. The basic point is that assigning an AnsiString (including the `CP_UTF8` specialization) to another AnsiString converts what is in the source to match the code page of the target string. A quirk for compatibility with presumably fpc ≤ 2.6.5 is that no such conversion will be done if one matches the source code CP and the other matches the system CP. In this case, forced (likely incorrect) interpretation as the target code page will occur.
445+
446+## See also
447+
448+- [[FPC Unicode support]]
449+- [[LCL Unicode Support]]
450+- [[TStringList-TStrings Tutorial]]
451+- [A Brief History of Strings](http://web.archive.org/web/20151125114234/http://www.codexterity.com/delphistrings.htm)
452+
453+---
454+*From the Free Pascal wiki, page "Character and string types", as it stood on 2023-12-14 after a change by Coz, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history