PChar: Difference between revisions
m (→comparative remarks: fix link destination) |
(consider changes suggested in discussion) |
||
Line 1: | Line 1: | ||
{{ | {{PChar}} | ||
The data type {{Doc|package=RTL|unit=system|identifier=pchar|text=<syntaxhighlight lang="pascal" inline> | The data type {{Doc|package=RTL|unit=system|identifier=pchar|text=<syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight>}} is a [[Pointer|pointer]] to a single [[Char|<syntaxhighlight lang="pascal" inline>char</syntaxhighlight>]]. | ||
{{Doc|package=RTL|unit=system|identifier=pansichar|text=<syntaxhighlight lang="pascal" inline>PAnsiChar</syntaxhighlight>}} is an alias for <syntaxhighlight lang="pascal" inline> | {{Doc|package=RTL|unit=system|identifier=pansichar|text=<syntaxhighlight lang="pascal" inline>PAnsiChar</syntaxhighlight>}} is an alias for <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight>. | ||
<syntaxhighlight lang="pascal">type | <syntaxhighlight lang="pascal">type | ||
PChar = ^char; | |||
PAnsiChar = PChar;</syntaxhighlight> | |||
== special support == | == special support == | ||
A <syntaxhighlight lang="pascal" inline> | A <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight> ''could'' be interpreted as a pointer to NULL-terminated string data type value on the heap. | ||
This means this string value ends with <syntaxhighlight lang="pascal" inline>chr(0)</syntaxhighlight>. | This means this string value ends with <syntaxhighlight lang="pascal" inline>chr(0)</syntaxhighlight>. | ||
This kind of storing data is rather unsafe and Pascal’s own string data types always indicate an explicit (maximum) length. | This kind of storing data is rather unsafe and Pascal’s own string data types always indicate an explicit (maximum) length. | ||
Line 14: | Line 14: | ||
=== direct assignments === | === direct assignments === | ||
A string literal can be assigned directly to a <syntaxhighlight lang="pascal" inline> | A string literal can be assigned directly to a <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight>: | ||
<syntaxhighlight lang="delphi"> | <syntaxhighlight lang="delphi"> | ||
program | program PCharDemo(output); | ||
var | var | ||
p: | p: PChar; | ||
begin | begin | ||
p := 'Foobar'; | p := 'Foobar'; | ||
Line 25: | Line 25: | ||
This assigns <syntaxhighlight lang="pascal" inline>p</syntaxhighlight> the address of an invisible ''constant'' value. | This assigns <syntaxhighlight lang="pascal" inline>p</syntaxhighlight> the address of an invisible ''constant'' value. | ||
That means you are not allowed to alter any component of this value. | That means you are not allowed to alter any component of this value. | ||
Something like <syntaxhighlight lang="pascal" inline style="white-space: nowrap;">p[0] := 'f'</syntaxhighlight> will crash. | |||
(Enforced since [[User Changes 3.0#Literal storage memory has been made read-only|FPC 3.0.0]]) | (Enforced since [[User Changes 3.0#Literal storage memory has been made read-only|FPC 3.0.0]]) | ||
=== routines === | === routines === | ||
[[Write|<syntaxhighlight lang="pascal" inline>Write</syntaxhighlight>/<syntaxhighlight lang="pascal" inline>writeLn</syntaxhighlight>]] can accept a <syntaxhighlight lang="pascal" inline> | [[Write|<syntaxhighlight lang="pascal" inline>Write</syntaxhighlight>/<syntaxhighlight lang="pascal" inline>writeLn</syntaxhighlight>]] can accept a <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight> and take it as a null-terminated string (provided the destination is a [[Text|<syntaxhighlight lang="pascal" inline>text</syntaxhighlight> file]]). | ||
Conversely [[WriteStr|<syntaxhighlight lang="pascal" inline>writeStr</syntaxhighlight>]] does not support <syntaxhighlight lang="pascal" inline> | Conversely [[WriteStr|<syntaxhighlight lang="pascal" inline>writeStr</syntaxhighlight>]] does not support <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight>. | ||
The standard [[RTL|run-time library]] provides many handy functions: | The standard [[RTL|run-time library]] provides many handy functions: | ||
Line 36: | Line 37: | ||
* All functions in the {{Doc|package=RTL|unit=strings|text=<syntaxhighlight lang="pascal" inline>strings</syntaxhighlight> unit}}. | * All functions in the {{Doc|package=RTL|unit=strings|text=<syntaxhighlight lang="pascal" inline>strings</syntaxhighlight> unit}}. | ||
There is also <syntaxhighlight lang="pascal" inline>{$modeSwitch | There is also <syntaxhighlight lang="pascal" inline>{$modeSwitch PCharToString}</syntaxhighlight>/<syntaxhighlight lang="bash" inline>‑MPCharToString</syntaxhighlight> ''automatically'' interpreting <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight> values as null-terminated strings and ''automatically'' converting them ''to'' the destination’s <syntaxhighlight lang="pascal" inline>string</syntaxhighlight> data type. | ||
=== data types === | === data types === | ||
The [[Ansistring#implementation|<syntaxhighlight lang="pascal" inline>ANSIString</syntaxhighlight> data type]] is a pointer to a <syntaxhighlight lang="pascal" inline>char</syntaxhighlight> and always ends with a ''complimentary'' null-Byte which allows direct [[Typecast|typecasting]] to <syntaxhighlight lang="pascal" inline> | The [[Ansistring#implementation|<syntaxhighlight lang="pascal" inline>ANSIString</syntaxhighlight> data type]] is a pointer to a <syntaxhighlight lang="pascal" inline>char</syntaxhighlight> and always ends with a ''complimentary'' null-Byte which allows direct [[Typecast|typecasting]] to <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight>: | ||
<syntaxhighlight lang="delphi" highlight="7">program | <syntaxhighlight lang="delphi" highlight="7">program ansiStringAsPCharDemo(output); | ||
var | var | ||
s: ANSIString; | s: ANSIString; | ||
p: | p: PChar; | ||
begin | begin | ||
s := 'foobar'; | s := 'foobar'; | ||
p := | p := PChar(s); | ||
writeLn(p); | writeLn(p); | ||
end.</syntaxhighlight> | end.</syntaxhighlight> | ||
Line 55: | Line 56: | ||
== caveats == | == caveats == | ||
The <syntaxhighlight lang="pascal" inline> | The <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight> data type used as a null-terminated string data type is rather an anomaly in the Pascal world. | ||
It has many caveats: | It has many caveats: | ||
* The definition of <syntaxhighlight lang="pascal" inline>char</syntaxhighlight> depends on <syntaxhighlight lang="pascal" inline>{$modeSwitch unicodeStrings}</syntaxhighlight>, 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|<syntaxhighlight lang="pascal" inline>inc( | * The definition of <syntaxhighlight lang="pascal" inline>char</syntaxhighlight> depends on <syntaxhighlight lang="pascal" inline>{$modeSwitch unicodeStrings}</syntaxhighlight>, 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|<syntaxhighlight lang="pascal" inline>inc(PCharVariable)</syntaxhighlight>]]. See [[FPC Unicode support]] for more details. | ||
* ''In Pascal'' a <syntaxhighlight lang="pascal" inline> | * ''In Pascal'' a <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight> is just that: a ''pointer'' to a single <syntaxhighlight lang="pascal" inline>char</syntaxhighlight> value. | ||
** That means the ''string concatenation'' [[Plus|operator <syntaxhighlight lang="pascal" inline>+</syntaxhighlight>]] does ''not'' work. If <syntaxhighlight lang="pascal" inline>{$pointerMath on}</syntaxhighlight> it will rather refer to arithmetic addition. You will need to use, for instance, {{Doc|package=RTL|unit=strings|identifier=strcat|text=<syntaxhighlight lang="pascal" inline>strings.strCat</syntaxhighlight>}} instead. | ** That means the ''string concatenation'' [[Plus|operator <syntaxhighlight lang="pascal" inline>+</syntaxhighlight>]] does ''not'' work. If <syntaxhighlight lang="pascal" inline>{$pointerMath on}</syntaxhighlight> it will rather refer to arithmetic addition. You will need to use, for instance, {{Doc|package=RTL|unit=strings|identifier=strcat|text=<syntaxhighlight lang="pascal" inline>strings.strCat</syntaxhighlight>}} instead. | ||
** Also the comparison operator <syntaxhighlight lang="pascal" inline>=</syntaxhighlight> will in fact compare ''addresses''. Use, for instance, {{Doc|package=RTL|unit=strings|identifier=strcomp|text=<syntaxhighlight lang="pascal" inline>strings.strComp</syntaxhighlight>}} to compare the referenced null-terminated string values, unless you really want to ensure two null-terminated strings are ''identical'' (= share the same memory). | ** Also the comparison operator <syntaxhighlight lang="pascal" inline>=</syntaxhighlight> will in fact compare ''addresses''. Use, for instance, {{Doc|package=RTL|unit=strings|identifier=strcomp|text=<syntaxhighlight lang="pascal" inline>strings.strComp</syntaxhighlight>}} to compare the referenced null-terminated string values, unless you really want to ensure two null-terminated strings are ''identical'' (= share the same memory). | ||
* Debugging is more difficult, confer [[FpDebug#Strings (vs PChar and Array of Char)|FPDebug]]. | * Debugging is more difficult, confer [[FpDebug#Strings (vs PChar and Array of Char)|FPDebug]]. | ||
Using a <syntaxhighlight lang="pascal" inline> | Using a <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight> ''just'' as a ''regular'' pointer to a ''single'' <syntaxhighlight lang="pascal" inline>char</syntaxhighlight>, however, does not have any special caveats. | ||
== comparative remarks == | == comparative remarks == | ||
* Delphi supports <syntaxhighlight lang="pascal" inline> | * Delphi supports <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight> as a null-terminated string. | ||
* The [[GNU Pascal|GPC]] has a special data type <syntaxhighlight lang="pascal" inline>CString</syntaxhighlight> which behaves like a null-terminated string. In GPC <syntaxhighlight lang="pascal" inline> | * The [[GNU Pascal|GPC]] has a special data type <syntaxhighlight lang="pascal" inline>CString</syntaxhighlight> which behaves like a null-terminated string. In GPC <syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight> is otherwise just a pointer. | ||
== see also == | == see also == | ||
* [[Character and string types]] | * [[Character and string types]] | ||
* [[Pascal for C users]] | * [[Pascal for C users]] |
Latest revision as of 14:14, 3 September 2021
│
Deutsch (de) │
English (en) │
español (es) │
français (fr) │
русский (ru) │
The data type PChar
is a pointer to a single char
.
PAnsiChar
is an alias for PChar
.
type
PChar = ^char;
PAnsiChar = PChar;
special support
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).
direct assignments
A string literal can be assigned directly to a PChar
:
program PCharDemo(output);
var
p: PChar;
begin
p := 'Foobar';
writeLn(p);
end.
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 FPC 3.0.0)
routines
Write
/writeLn
can accept a PChar
and take it as a null-terminated string (provided the destination is a text
file).
Conversely writeStr
does not support PChar
.
The standard run-time library provides many handy functions:
system.strlen
determines the length of a null-terminated string. Thelength
function does this too.system.strPas
converts a null-terminated string to ashortString
.- All functions in the
strings
unit.
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.
data types
The ANSIString
data type is a pointer to a char
and always ends with a complimentary null-Byte which allows direct typecasting to PChar
:
program ansiStringAsPCharDemo(output);
var
s: ANSIString;
p: PChar;
begin
s := 'foobar';
p := PChar(s);
writeLn(p);
end.
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.

uniqueString
before you do the typecast.caveats
The PChar
data type used as a null-terminated string data type is rather an anomaly in the Pascal world.
It has many caveats:
- 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(PCharVariable)
. See FPC Unicode support for more details. - In Pascal a
PChar
is just that: a pointer to a singlechar
value.- That means the string concatenation operator
+
does not work. If{$pointerMath on}
it will rather refer to arithmetic addition. You will need to use, for instance,strings.strCat
instead. - Also the comparison operator
=
will in fact compare addresses. Use, for instance,strings.strComp
to compare the referenced null-terminated string values, unless you really want to ensure two null-terminated strings are identical (= share the same memory).
- That means the string concatenation operator
- Debugging is more difficult, confer FPDebug.
Using a PChar
just as a regular pointer to a single char
, however, does not have any special caveats.
comparative remarks
- Delphi supports
PChar
as a null-terminated string. - The GPC has a special data type
CString
which behaves like a null-terminated string. In GPCPChar
is otherwise just a pointer.