Written by rdc
什么是指针?
指针是一个4字节的数据类型,将地址保存到存储器位置。指针不包含数据,一旦它被初始化,它就指向数据。未初始化的指针指向什么也不定义。
要了解指针,想想一个打印在每个“洞”底部(你放置鸡蛋)的数字1到12的蛋纸箱。这些孔像计算机中的记忆位置一样;每个孔或存储器位置都有一个地址,在本例中为1到12。如果一个蛋代表一个数据项,则孔1中的一个地址为1。
通常,您将通过使用变量直接访问数据。当DIM DIM是特定类型的变量时,您将为数据预留存储空间。您不需要知道或关心数据所在的位置,因为您可以通过变量直接访问数据。这就像在孔1(读数据)中拿出蛋,拿一个鸡蛋放入孔1(设置数据),而不必查看写在孔底部的数字。
使用指针有点不一样。想象一下,你有一点点的纸会代表我们的指针。现在是空白的,不指向任何东西。这个未定义的指针在初始化之前不能使用。要初始化指针,请在其上写入1。现在我们的指针是“指向”我们蛋盒中的孔1。将数据(鸡蛋)放入孔1中,我们看看我们的废纸,将其与孔1匹配,并将鸡蛋放在孔中。要检索蛋,我们做的恰恰相反。我们将我们的纸张与孔1匹配,然后抓住鸡蛋。鸡蛋的所有放置和获取必须通过纸张的纸张完成,并称为取消引用指针。也就是说,我们通过指针中包含的参考数字获得数据,数字1。指针不包含数据;它包含对数据的引用。
在FreeBasic中,我们使用
暗淡和
PTR语句定义了一个指针:
Dim aptr As Integer Ptr
这个声明对应于上述例子中的空白纸。指针不指向任何东西,未定义。如果我们现在试图使用指针,程序就可能会崩溃。
为了使指针变得有用,它必须被初始化:
Dim aptr As Integer Ptr
aptr = Allocate(SizeOf(Integer))
这里我们使用
赋值在
整数的内存中留出足够的空间,并将该空间的地址加载到aptr中。
SizeOf宏返回传递数据类型的大小(以字节为单位)。如果你愿意,你可以使用len而不是
SizeOf(自.13b)。
一旦我们初始化了指针,我们现在可以使用它:
*aptr = 5
Print "aptr: "; *aptr
注意aptr上的
*前缀。*是参考运算符。这就像将纸张上的数字与蛋盒上的孔数相匹配。通过使用*运算符,我们可以得到aptr指向的孔中包含的数据(egg)。
这是一个完整的示例程序:
Option Explicit
Dim aptr As Integer Ptr
aptr = Allocate(SizeOf(Integer))
*aptr = 5
Print "aptr: "; *aptr
Deallocate aptr
Sleep
取消赋值函数释放aptr指向的内存,并再次使aptr未定义。这就像删除我们的纸上的数字。如果我们在取消赋值后使用aptr,程序会崩溃。
指针有什么好处?
添加指向FreeBasic的主要原因是许多外部库需要指向键入结构和指向字符串的指针。例如,Win32 API有许多结构必须填写,然后通过指针传递给一个函数。
指针的另一个用法在于
类型定义。
类型在FreeBasic中的defs只能包含固定长度的字符串,但是如果在程序运行之前不知道字符串的长度怎么办?指针可以用于此目的。
(应该说,类型定义现在可以支持可变长度的字符串。)
Option Explicit
Type mytptr
sptr As ZString Ptr
End Type
'This function will allocate space for the passed string
'and load it into a memory location, returning the
'pointer to the string.
Declare Function pSetString(ByVal s As String) As ZString Ptr
'type var
Dim mytype As mytptr
'Set a variable string into the type def
mytype.sptr = pSetString("Hello World From FreeBasic!")
Print "aptr: "; *mytype.sptr
Deallocate(mytype.sptr)
Sleep
End
Function pSetString(ByVal s As String) As ZString Ptr
Dim sz As ZString Ptr
'allocate some space + 1 for the chr(0)
sz = Allocate(Len(s) + 1)
'load the string into the memory location
*sz = s
'return the pointer
Return sz
End Function
这里我们用字段sptr定义我们的类型为
ZStringPTR.Zstrings是空终止的字符串,被许多外部库使用,被设计用于动态赋值。一旦我们定义了我们的类型,我们使用
暗淡语句创建一个实例:
Dim mytype As mytptr
然后我们调用我们的函数pSetString来获取我们在
类型def中所需的可变长度字符串的地址。
mytype.sptr = pSetString("Hello World From FreeBasic!")
记住sptr被定义为一个指针,而不是一个字符串变量,所以pSetString返回一个指针(内存地址)到字符串而不是字符串本身。换句话说,如果字符串在#1中,pSetString返回1。
函数pSetString使用临时
ZStringsz,到
赋值传递的字符串参数的空间。因为
ZString是一个空值终止的字符串,我们必须在
赋值函数中为空终止符的长度添加1。
'allocate some space + 1 for the chr(0)
sz = Allocate(Len(s) + 1)
一旦我们为字符串赋值空间,我们使用引用运算符*将数据加载到内存位置。
'load the string into the memory location
*sz = s
然后我们返回一个指针(字符串的地址)回到我们的类型,它保存在mytype.sptr中。
'return the pointer
Return sz
我们现在可以使用引用运算符来引用我们类型中的字符串。
Print "aptr: "; *mytype.sptr
指针可能会让未知的人感到困惑,但是如果记住指针不包含数据,那么它们不需要,它只是指向一些数据。指针是一个内存地址,您可以通过引用运算符*操作该数据。它和一个正常的变量真的没有什么不同。