【问题标题】:Is there any compiler magic in PChar / PWideChar / PAnsiChar casts?PChar / PWideChar / PAnsiChar 转换中是否有任何编译器魔法?
【发布时间】:2013-02-20 13:20:42
【问题描述】:

我经常读到编译器在转换为 PChar 时会产生某种魔力。

PChar 的主要目的是调用库中的外部代码,这些库需要一个以零结尾的字符数组(C 风格的“字符串”)。

PChar 在 Unicode Delphi 上是 PWideChar 的别名,在非 Unicode Delphi 上是 PAnsiChar 的别名。

另一方面,Delphi 字符串(string = AnsiString / UnicodeString,我不是在谈论 WideString,更不用说 ShortString ...)另一方面具有隐藏长度而不是终止字符。它们也被引用计数并在写入时使用复制。

Delphi 字符串是否自动分配并使用隐式 #0 字符保持一个字符长,以便更轻松地转换为 PChar (PAnsiChar / PWideChar) 或者编译器在遇到字符串时会检查和调整字符串吗?转换为PChar?

【问题讨论】:

  • 我不怀疑大多数 开发人员使用PChar 及其同类的主要原因是调用外部代码,但这不是他们的字面目的。它们是 Delphi 中定义的各种字符串类型的指针类型。从技术角度来看,仅此而已。
  • @LaKraven PChar 周围的所有魔力使它不仅仅是一个指针。

标签: string delphi pointers casting


【解决方案1】:

流程如下:

  • 如果字符串s 的长度大于零,则PChar(s) 返回指向字符串内容第一个元素的指针。因为 string 被管理有一个 hidden 空终止符,所以无需再做任何事情。
  • 如果字符串s 的长度为零,则PChar(s) 返回指向包含空终止符的内存块的指针。

作为一个实现细节,从PChar(nil) 返回的空终止符是在已编译模块的只读部分中分配的全局常量。

为了使转换为 PChar (PAnsiChar / PWideChar) 更容易,是否会自动分配 Delphi 字符串并使用隐式 #0 字符保持一个字符长?

是的。

如果可以这么说的话,神奇之处在于:

  1. 对空字符串使用PChar() 会返回一个指向空终止符的指针。
  2. Delphi 在字符串末尾保留 hidden 空终止符。

【讨论】:

  • @Jens - 也许是“编译器内在”?例如,当编译器看到 PChar 转换时,它会生成对“_USrToPWChar”的调用。
  • @SertacAkyuz 听起来很合理。用外行的话来说可能是“特殊处理”?毕竟与正常的转换相比,编译器在这里做了一些不寻常的事情。
  • @Jens - 它可能更合适,是的。 :)
  • 编译魔法是一个常用的术语。在文档中,他们使用术语编译器内在来表示相同的意思。至少我是这么理解的。
【解决方案2】:

字符串变量内部是指向包含前缀、字符和空终止符的结构的指针。虽然结构从前缀开始(包含字符串长度、引用计数、字符大小和代码页),但指针指向第一个字符,因此转换为 PChar 很简单。

字符串 -> PChar 转换的神奇之处在于始终PChar(S) <> nil,即使字符串为空(S = ''Pointer(S) = nil)。 PChar(S) 不是像Pointer(S) 那样“按原样”返回字符串变量指针,而是调用一个函数来检查Pointer(S) 是否为nil,如果Pointer(S) = nil 返回一个指向虚拟空字符串的指针而不是nil (即指向虚拟空字符串的空终止符的指针)。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多