PChar: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: PChar
| Old | New | Line | |
|---|---|---|---|
| 1 | + | The data type [`PChar`](https://www.freepascal.org/docs-html/rtl/system/pchar.html) is a [[Pointer|pointer]] to a single [[Char|char]]. [`PAnsiChar`](https://www.freepascal.org/docs-html/rtl/system/pansichar.html) is an alias for `PChar`. | |
| 2 | + | ||
| 3 | + | ``` pascal | |
| 4 | + | type | |
| 5 | + | PChar = ^char; | |
| 6 | + | PAnsiChar = PChar; | |
| 7 | + | ``` | |
| 8 | + | ||
| 9 | + | ## special support | |
| 10 | + | ||
| 11 | + | A `PChar` *could* be interpreted as a pointer to NULL-terminated string data type value on the heap. This means this string value ends with `chr(0)`. This kind of storing data is rather unsafe and Pascal’s own string data types always indicate an explicit (maximum) length. However, many libraries written in other programming languages make use of this dangerous data type and in order to facilitate interaction with them the [[FPC]] provides special support (only available in *non*-ISO modes). | |
| 12 | + | ||
| 13 | + | ### direct assignments | |
| 14 | + | ||
| 15 | + | A string literal can be assigned directly to a `PChar`: | |
| 16 | + | ||
| 17 | + | ```delphi | |
| 18 | + | program PCharDemo(output); | |
| 19 | + | var | |
| 20 | + | p: PChar; | |
| 21 | + | begin | |
| 22 | + | p := 'Foobar'; | |
| 23 | + | writeLn(p); | |
| 24 | + | end. | |
| 25 | + | ``` | |
| 26 | + | ||
| 27 | + | This assigns `p` the address of an invisible *constant* value. That means you are not allowed to alter any component of this value. Something like `p[0] := 'f'` will crash. (Enforced since [[User Changes 3.0|FPC 3.0.0]]) | |
| 28 | + | ||
| 29 | + | ### routines | |
| 30 | + | ||
| 31 | + | [[Write|Write/writeLn]] can accept a `PChar` and take it as a null-terminated string (provided the destination is a [[Text|text file]]). Conversely [[WriteStr|writeStr]] does not support `PChar`. | |
| 32 | + | ||
| 33 | + | The standard [[RTL|run-time library]] provides many handy functions: | |
| 34 | + | ||
| 35 | + | - [`system.strlen`](https://www.freepascal.org/docs-html/rtl/system/strlen.html) determines the length of a null-terminated string. The `length` function does this too. | |
| 36 | + | - [`system.strPas`](https://www.freepascal.org/docs-html/rtl/system/strpas.html) converts a null-terminated string to a [[Shortstring|shortString]]. | |
| 37 | + | - All functions in the [`strings` unit](https://www.freepascal.org/docs-html/rtl/strings/index.html). | |
| 38 | + | ||
| 39 | + | There is also `{$modeSwitch PCharToString}`/`‑MPCharToString` *automatically* interpreting `PChar` values as null-terminated strings and *automatically* converting them *to* the destination’s `string` data type. | |
| 40 | + | ||
| 41 | + | ### data types | |
| 42 | + | ||
| 43 | + | The [[Ansistring|ANSIString data type]] is a pointer to a `char` and always ends with a *complimentary* null-Byte which allows direct [[Typecast|typecasting]] to `PChar`: | |
| 44 | + | ||
| 45 | + | ```delphi | |
| 46 | + | program ansiStringAsPCharDemo(output); | |
| 47 | + | var | |
| 48 | + | s: ANSIString; | |
| 49 | + | p: PChar; | |
| 50 | + | begin | |
| 51 | + | s := 'foobar'; | |
| 52 | + | p := PChar(s); | |
| 53 | + | writeLn(p); | |
| 54 | + | end. | |
| 55 | + | ``` | |
| 56 | + | ||
| 57 | + | Beware that this works well only as long as you are merely *reading from* the typecasted value. Also note that an `ANSIString` *is allowed* to contain `chr(0)` *as* payload. | |
| 58 | + | ||
| 59 | + | > **Note:** If you intend to *alter* data *via* the pointer, you possibly want to call [`uniqueString`](https://www.freepascal.org/docs-html/rtl/system/uniquestring.html) before you do the typecast. | |
| 60 | + | ||
| 61 | + | ## caveats | |
| 62 | + | ||
| 63 | + | The `PChar` data type used as a null-terminated string data type is rather an anomaly in the Pascal world. It has many caveats: | |
| 64 | + | ||
| 65 | + | - The definition of `char` depends on `{$modeSwitch unicodeStrings}`, that means in FPC 3.2.0 it could either refer to a 1‑Byte or 2‑Byte quantity. Most noticeably, this affects the offset if you are using pointer arithmetic, e. g. [[Inc and DecSpecial behaviors|inc(PCharVariable)]]. See [[FPC Unicode support]] for more details. | |
| 66 | + | - *In Pascal* a `PChar` is just that: a *pointer* to a single `char` value. | |
| 67 | + | - That means the *string concatenation* [[Plus|operator +]] does *not* work. If `{$pointerMath on}` it will rather refer to arithmetic addition. You will need to use, for instance, [`strings.strCat`](https://www.freepascal.org/docs-html/rtl/strings/strcat.html) instead. | |
| 68 | + | - Also the comparison operator `=` will in fact compare *addresses*. Use, for instance, [`strings.strComp`](https://www.freepascal.org/docs-html/rtl/strings/strcomp.html) to compare the referenced null-terminated string values, unless you really want to ensure two null-terminated strings are *identical* (= share the same memory). | |
| 69 | + | - Debugging is more difficult, confer [[FpDebug|FPDebug]]. | |
| 70 | + | ||
| 71 | + | Using a `PChar` *just* as a *regular* pointer to a *single* `char`, however, does not have any special caveats. | |
| 72 | + | ||
| 73 | + | ## comparative remarks | |
| 74 | + | ||
| 75 | + | - Delphi supports `PChar` as a null-terminated string. | |
| 76 | + | - The [[GNU Pascal|GPC]] has a special data type `CString` which behaves like a null-terminated string. In GPC `PChar` is otherwise just a pointer. | |
| 77 | + | ||
| 78 | + | ## see also | |
| 79 | + | ||
| 80 | + | - [[Character and string types]] | |
| 81 | + | - [[Pascal for C users]] | |
| 82 | + | ||
| 83 | + | --- | |
| 84 | + | *From the Free Pascal wiki, page "PChar", as it stood on 2021-09-03 after a change by Kai Burghardt, 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).* |
