To
manipulate null-terminated strings, it is often necessary to use pointers. (See
Pointers and pointer
types.) String constants are assignment-compatible with the PChar
and PWideChar types, which represent pointers to null-terminated arrays
of Char and WideChar values. For example,
var
P: PChar;
...
P :=
'Hello world!';
points P to an area of memory that contains
a null-terminated copy of ‘Hello world!’. This is equivalent to
const
TempString: array[0..12] of Char = 'Hello world!'#0;
var
P: PChar;
...
P :=
@TempString;
You can
also pass string constants to any function that takes value or const
parameters of type PChar or PWideChar. For example StrUpper('Hello
world!'). As with assignments to a PChar, the compiler generates a
null-terminated copy of the string and gives the function a pointer to that
copy. Finally, you can initialize PChar or PWideChar constants with
string literals, alone or in a structured type. Examples:
const
Message:
PChar = 'Program terminated';
Prompt: PChar = 'Enter values: ';
Digits: array[0..9] of
PChar = (
'Zero', 'One', 'Two',
'Three', 'Four',
'Five', 'Six', 'Seven',
'Eight', 'Nine');
Zero-based
character arrays are compatible with PChar and PWideChar. When
you use a character array in place of a pointer value, the compiler converts
the array to a pointer constant whose value corresponds to the address of the
first element of the array. For example,
var
MyArray: array[0..32] of
Char;
MyPointer: PChar;
begin
MyArray := 'Hello';
MyPointer := MyArray;
SomeProcedure(MyArray);
SomeProcedure(MyPointer);
end;
This code
calls SomeProcedure twice with the same value.
A
character pointer can be indexed as if it were an array. In the example above,
MyPointer[0] returns H. The index specifies an offset added to the pointer
before it is dereferenced. (For PWideChar variables, the index is
automatically multiplied by two.) Thus, if P is a character pointer, P[0] is
equivalent to P^ and specifies the first character in the array, P[1] specifies
the second character in the array, and so forth; P[-1] specifies the character
immediately to the left of P[0]. The compiler performs no range checking on
these indexes.
The StrUpper
function illustrates the use of pointer indexing to iterate through a
null-terminated string:
function
StrUpper(Dest, Source: PChar; MaxLen: Integer): PChar;
var
I: Integer;
begin
I := 0;
while (I < MaxLen) and
(Source[I] <> #0) do
begin
Dest[I] :=
UpCase(Source[I]);
Inc(I);
end;
Dest[I] := #0;
Result := Dest;
end;
Mixing
Pascal strings and null-terminated strings
Working with null-terminated strings
处理空结束串通常必需使用指针(见指针和指针类型)。串常量对PChar和PWideChar类型是赋值兼容的,这两种类型也表示指向Char和WideChar类型空结束数组的指针的值。例如,
var
P: PChar;
...
P :=
'Hello world!';
赋值语句将P指向包含空结束串
’Hell world!’ 副本的内存区域。上面的语句等价于
const
TempString: array[0..12] of Char = 'Hello world!'#0;
var
P: PChar;
...
P :=
@TempString;
也可以将串常量传递给所有接受PChar或PWideChar值或const参数的函数,如StrUpper('Hello world!')。对PChar赋值时,编译器产生一个该串的空结束副本并将指向该副本的指针赋给PChar变量。还可以用文本串初始化PChar或PWideChar,包括单独类型和结构类型。例如:
const
Message:
PChar = 'Program terminated';
Prompt: PChar = 'Enter values: ';
Digits: array[0..9] of
PChar = (
'Zero', 'One', 'Two',
'Three', 'Four',
'Five', 'Six', 'Seven',
'Eight', 'Nine');
零基字符数组也对PChar和PWideChar兼容。当用字符数组代替指针的值时,编译器将把数组变换成一个指针常量,该指针常量的值对应着数组中第一个元素所在的地址。例如:
var
MyArray: array[0..32] of
Char;
MyPointer: PChar;
begin
MyArray := 'Hello';
MyPointer := MyArray;
SomeProcedure(MyArray);
SomeProcedure(MyPointer);
end;
上面的代码中,SomeProcedure过程两次调用接受的参数是相同的值。
如果字符指针指向的是字符数组,那么字符指针是可以被索引的。在上面的例子中,MyPointer[0]返回字母H。在字符指针被解除参照之前,其索引是指对指针地址增加的偏移量。(对PWideChar变量,索引自动被乘以2。)因此,如果P是一个字符指针,那么P[0]等价于P^,表示的是数组中第一个字符,P[1]表示数组中的第二个字符,等等;P[-1]表示的是紧邻P[0]左边的字符(如果使用类似索引,不能确定是导致非法地址访问,也不能确定访问到的字符来自何处)。编译器对字符指针索引是不做范围检查的(因此需要小心使用)。
下面的StrUpper函数举例说明了遍历空结束串时字符指针索引的使用:
function
StrUpper(Dest, Source: PChar; MaxLen: Integer): PChar;
var
I: Integer;
begin
I := 0;
while (I < MaxLen) and
(Source[I] <> #0) do
begin
Dest[I] :=
UpCase(Source[I]);
Inc(I);
end;
Dest[I] := #0;
Result := Dest;
end;