我经常读到编译器在转换为PChar
时会发挥某种魔力。
PChar
的主要用途是调用库中的外部代码,这些代码需要一个以零结尾的字符数组(C风格的"字符串")。
PChar
是一种类型,在Unicode Delphi上是PWideChar
的别名,在非Unicode Delphi中是PAnsiChar
的别名。
另一方面,Delphi字符串(string
=AnsiString
/UnicodeString
,我在这里不是在谈论WideString
,更不用说ShortString
了…)具有隐藏长度,而不是终止字符。它们也被引用计数,并使用写时复制。
Delphi字符串是自动分配并保持为一个字符长,带有隐式#0字符,以便更容易转换为PChar
(PAnsiChar/PWideChar),还是编译器在遇到转换为PChar
时检查并调整字符串?
过程如下:
- 如果字符串
s
的长度大于零,则PChar(s)
返回指向字符串内容的第一个元素的指针。因为string
被管理为具有隐藏的空终止符,所以不需要再做任何事情 - 如果字符串
s
的长度为零,则PChar(s)
返回一个指向包含空终止符的内存块的指针
作为实现细节,从PChar(nil)
返回的null终止符是在编译模块的只读部分中分配的全局常量。
Delphi字符串是否自动分配并保持为一个字符长,带有隐式#0字符,以便更容易转换为PChar(PAnsiChar/PWideChar)?
是的。
神奇之处,如果你可以这么说的话,就是:
- 对空字符串使用
PChar()
会返回一个指向空终止符的指针 - Delphi在字符串末尾维护隐藏的null终止符
字符串->PChar铸造的神奇之处在于,即使字符串为空(S = ''
和Pointer(S) = nil
),也始终是PChar(S) <> nil
。PChar(S)
不像Pointer(S)
那样返回字符串变量指针"原样",而是调用一个函数来检查Pointer(S)
是否为零,以及Pointer(S) = nil
是否返回指向伪空字符串而不是nil
的指针(即指向伪空串的空终止符的指针)。