(Delphi) 指针和指针类型

45次阅读
没有评论

PS:英语好的可以看原文,这里只是机翻加我自己理解调整后的中文。

指针是表示内存地址的变量。当指针持有另一个变量的地址时,我们说它指向该变量在内存中的位置或存储在内存中的数据。对于数组或其他结构化类型,指针保存结构中第一个元素的地址。如果已经获取了该地址,那么指针将保存指向第一个元素的地址。

指针类型是为了表示存储在它们所持有的地址上的数据类型。通用指针类型可以表示指向任何数据的指针,而专门的指针类型只引用特定类型的数据。PByte类型用于非字符数据的任何字节数据。

在32位平台上,指针使用32位地址占用四个字节的内存。在64位平台上,指针使用64位地址占用8个字节的内存。

本主题包含以下方面的信息:

指针类型的一般概述。

声明并使用Delphi支持的指针类型。

 1         var
 2           X, Y: Integer;  // X and Y are Integer variables
 3           P: ^Integer;     // P points to an Integer
 4         begin
 5           X := 17;      // assign a value to X
 6           P := @X;      // assign the address of X to P
 7           Y := P^;      // dereference P; assign the result to Y
 8         end;

第2行:将X和Y声明为Integer类型的变量。

第3行:将P声明为指向整数值的指针;这意味着P可以指向X或Y的位置。

第5行:给X赋值,

第6行:为P分配X的地址(由@X表示)。

第7行:检索P(由P ^ 表示)所指向位置的值并将其分配给Y。

执行此代码后,X和Y具有相同的值,即17。

此处用于获取变量地址的@操作符也对函数和过程进行操作。有关详细信息,请参见语句和表达式中的@Operatorproduceral类型。@操作符在文章末尾也有部分翻译。

符号^有两个用途,在我们的示例中说明了这两个用途。当它出现在类型标识符之前时:

^typeName

表示指向typeName类型变量的指针的类型。

当插入符号出现在指针变量之后时:

pointer^

表示撤销指针;也就是说,它返回存储在指针所保存的内存地址中的值。

这个例子似乎是一种将一个变量的值复制到另一个变量的迂回方式——我们可以用一个简单的赋值语句来完成这一点。但指针之所以有用有几个原因。首先,理解指针将有助于您理解Delphi语言,因为指针通常在代码中的幕后操作,而这些代码并不显式出现。任何需要动态分配大内存块的数据类型都使用指针。例如,长字符串变量和类实例变量都是隐式指针。此外,一些高级编程技术需要使用指针。

最后,指针有时是绕过Delphi严格的数据类型的唯一方法。通过使用通用指针引用变量,将指针强制转换为更特定的类型,然后取消引用,可以将任何变量存储的数据视为属于任何类型。例如,以下代码将存储在实变量中的数据分配给整数变量:

type
  PInteger = ^Integer;
var
  R: Single;
  I: Integer;
  P: Pointer;
  PI: PInteger;
begin
  ...
  P := @R;
  PI := PInteger(P);
  I := PI^;
end;

当然,实数和整数以不同的格式存储。这个赋值只是将原始二进制数据从R复制到I,而不进行转换。

除了分配@运算的结果外,还可以使用几个标准例程为指针赋值。New和GetMem过程将内存地址分配给现有指针,而Addr和Ptr函数将返回指向指定地址或变量的指针。

取消引用指针可以是限定的,并且可以用作限定符,如表达式P1^.Data^。

保留字nil是一个特殊常量,可以分配给任何指针。将nil指定给指针时,指针不引用任何内容。

未完待续…..

指针类型

您可以使用以下语法声明指向任何类型的指针:

类型指针类型名称= ^ 类型

type pointerTypeName = ^type

定义记录或其他数据类型时,还定义指向该类型的指针可能很有用。这使得在不复制大内存块的情况下操作该类型的实例变得容易。

注意:您可以在声明指针类型之前声明它指向的类型。

其他标准指针类型

SystemSysUtils单位声明常用很多标准指针类型。

使用该{POINTERMATH <ON|OFF>}指令为所有类型指针打开或关闭指针运算,以便按元素大小进行递增/递减。

System 和 SysUtils 中声明的选定指针类型

指针类型 指向类型变量
PString Unicode字符串
PAnsiString AnsiString字符串
PByteArray
TByteArray
(中声明
SysUtils单元)。
用于为数组访问类型转换动态分配的内存。
PCurrencyPDoublePExtendedPSingle 货币,
双精度,
扩展,
单精度
PInteger 整数
POleVariant 变体
PShortString 短字符串
在移植使用旧
PString类型的
遗留代码时很有用
PTextBuf TTextBuf(中声明
SysUtils单元)。
TTextBuf
TTextRec文件记录中
的内部缓冲区类型
。)
PVarRec TVarRec(在
System 中声明
PVariant 变体
PWideString 宽字符串
PWordArray TWordArray(中声明
SysUtils单元)。
用于为 2 字节值的数组类型转换动态分配的内存

@操作符或叫运算符

@运算符返回变量或函数、过程或方法的地址;也就是说,@构造一个指向其操作数的指针。以下规则适用于@。

如果X是一个变量,@X返回X的地址。

当X是一个过程变量时,特殊规则适用;请参阅关于数据类型(Delphi)中的“语句和表达式中的过程类型”。

@X的类型是指针,如果默认的{$T}编译器指令有效。在{$T+}状态中,@X是^T类型,其中T是X的类型(这种区别对于赋值兼容性很重要,请参阅赋值兼容性)。

如果F是一个例程(函数或过程),@F返回F的入口点。@F的类型始终是指针。

将@应用于类中定义的方法时,方法标识符必须使用类名限定。

@TMyClass.DoSomething

指向TMyClass的类型方法。有关类和方法的更多信息,请参见类和对象(Delphi)。

注意:当使用@operator时,不可能获取接口方法的地址,因为地址在编译时未知,在运行时无法提取。

@与NOT在操作符中 拥有最高的优先运算级

正文完