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。
此处用于获取变量地址的@操作符也对函数和过程进行操作。有关详细信息,请参见语句和表达式中的@Operator和produceral类型。@操作符在文章末尾也有部分翻译。
符号^有两个用途,在我们的示例中说明了这两个用途。当它出现在类型标识符之前时:
^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
定义记录或其他数据类型时,还定义指向该类型的指针可能很有用。这使得在不复制大内存块的情况下操作该类型的实例变得容易。
注意:您可以在声明指针类型之前声明它指向的类型。
其他标准指针类型
该System
和SysUtils
单位声明常用很多标准指针类型。
使用该{POINTERMATH <ON|OFF>}
指令为所有类型指针打开或关闭指针运算,以便按元素大小进行递增/递减。
System 和 SysUtils 中声明的选定指针类型
指针类型 | 指向类型变量 |
PString | Unicode字符串 |
PAnsiString | AnsiString字符串 |
PByteArray | TByteArray(中声明 SysUtils单元)。 用于为数组访问类型转换动态分配的内存。 |
PCurrency, PDouble, PExtended, PSingle | 货币, 双精度, 扩展, 单精度 |
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在操作符中 拥有最高的优先运算级