Delphi 指针[1]关于Pointers 和@操作符
Delphi 指针[1]关于Pointers 和@操作符
1、指针(Pointers)概念
指针是表示内存地址的变量。当一个指针保存另一个变量的地址时,我们称它指向该变量在内存中的位置或存储在那里的数据。在数组或其他结构化类型的情况下,指针保存结构中第一个元素的地址。如果该地址已经被占用,那么指针将保存第一个元素的地址。
指针被键入以指示存储在它们所保存的地址处的数据类型。通用指针类型可以表示指向任何数据的指针,而更专门的指针类型仅引用特定类型的数据。指针占用四个字节的内存。
2、指针工作
指针是如何工作的,例如:
1 var
2 X, Y: Integer; // X和Y是整数变量
3 P: ^Integer; // P指向一个整数
4 begin
5 X := 17; // 给X赋值
6 P := @X; //将X的地址分配给P
7 Y := P^; // 去参考P;将结果分配给Y,Y的结果:17
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指定给指针时,指针不引用任何内容。
2、关于@操作符
@运算符返回变量或函数、过程或方法的地址;也就是说,@构造一个指向其操作数的指针。
以下规则适用于@:
- 如果X是一个变量,@X返回X的地址(当X是程序变量时,特殊规则适用;请参阅语句和表达式中的过程类型。)如果默认的{$T-}编译器指令有效,@X的类型是指针。在{$T+}状态下,@X是^T类型,其中T是X的类型(这种区别对于赋值兼容性很重要,请参见第5-36页的“赋值兼容性”)。
- 如果F是一个例程(函数或过程),@F返回F的入口点。@F的类型始终是指针。
- 将@应用于类中定义的方法时,方法标识符必须使用类名限定。例如:
- @TMyClass.DoSomething
- 指向TMyClass的剂量测定方法。有关类和方法的更多信息,请参见类和对象。
注意:当使用@运算符时,不可能获取接口方法的地址,因为该地址在编译时未知,并且无法在运行时提取。
创建时间:2021.08.12 更新时间:2022.12.13