Pointers, Data Types and Memory
 
Written by rdc

如果您阅读文章指针简介,您将知道指针包含内存位置地址。您可以使用参考运算符*来处理这些存储单元中的数据。使用单个数据项的指针不是一个问题,但是如果您需要将多个数据项存储在一起并使用指针进行操作,该怎么办?它可以有点棘手,除非你了解数据如何存储在内存中。

计算机中的单个内存位置为1字节长。足够大以容纳一个ANSI字符(而不是Unicode字符,它们是宽字符并且是两个字节。我们在本文中不讨论Unicode字符。)但是,所有数据类型的宽度不是单个字节。这是一个简单的程序,显示每个数据类型的字节长度。

Dim a As Byte
Dim b As Short
Dim c As Integer
Dim d As LongInt
Dim au As UByte
Dim bu As UShort
Dim cu As UInteger
Dim du As ULongInt
Dim e As Single
Dim f As Double
Dim g As Integer Ptr
Dim h As Byte Ptr
Dim s1 As String * 10 'fixed string
Dim s2 As String      'variable length string
Dim s3 As ZString Ptr 'zstring


s1 = "Hello World!"
s2 = "Hello World from FreeBasic!"
s3 = Allocate( Len( s2 ) + 1 )
*s3 = s2

Print "Byte: ";Len(a)
Print "Short: ";Len(b)
Print "Integer: ";Len(c)
Print "Longint: ";Len(d)
Print "UByte: ";Len(au)
Print "UShort: ";Len(bu)
Print "UInteger: ";Len(cu)
Print "ULongint: ";Len(du)
Print "Single: ";Len(e)
Print "Double: ";Len(f)
Print "Integer Pointer: ";Len(g)
Print "Byte Pointer: ";Len(h)
Print "Fixed String: ";Len(s1)
Print "Variable String: ";Len(s2)
Print "ZString: ";Len(*s3)

Deallocate s3

Sleep



输出为:

Byte:  1
Short:  2
Integer:  4
LongInt:  8
UByte:  1
UShort:  2
UInteger:  4
ULongInt:  8
Single:  4
Double:  8
Integer Pointer:  4
Byte Pointer:  4
Fixed String:  10
Variable String:  27
ZString:  27



请注意,指针的长度始终为4个字节长(与整数相同),无论指向的数据如何,因为指针包含内存地址而不是数据。

查看不同数据类型的长度,您可以看到,如果您要赋值足够的空间用于10个整数,则需要40个字节的内存。每个整数占用4个字节。所以问题是,你如何从内存缓冲区访问每个整数值?答案,指针数学。看看下面的程序。

Option Explicit

Dim a As Integer
Dim aptr As Integer Ptr

'Allocate enough space for 2 integers
aptr = Allocate(Len(a) * 2)
'Load our first integer
*aptr = 1
Print "Int #1: ";*aptr
'Move the pointer to the next integer position
'aptr + 4
*(aptr + 4) = 2
Print "Int #2: ";*(aptr + 4)

Deallocate aptr
Sleep
End



在这个程序中,我们定义了两个变量,一个整数和一个整数指针,aptr。Aptr将指向将包含两个整数的内存缓冲区。赋值函数需要我们需要的缓冲区的大小,所以我们将整数的大小乘以2,以保留8个字节的内存(每个整数将占用4个字节的空间)。

在赋值过程之后,aptr包含我们的内存缓冲区的第一个字节的地址。存储第一个整数只是使用参考运算符并将值设置为1的问题。要打印出值,我们再次使用* aptr。

现在,我问你一个问题:编译器如何知道值1需要4个字节而不是1或2个字节?因为我们将aptr定义为integer ptr .编译器知道一个整数需要4个字节,因此将数据加载到四个字节的内存中。这就是为什么当我们打印出我们得到的值1而不是一些奇怪的数字。

要将第二个值加载到缓冲区中,我们使用:

*(aptr + 4) = 2



这可能看起来有点奇怪乍一看。Aptr指向我们的内存缓冲区中的第一个字节。一个整数是4个字节长,所以要到下一个整数字节的位置,我们必须添加4到aptr。我们需要添加操作的括号,因为引用运算符*的优先级高于+。括号确保我们先执行添加操作,然后应用间接运算符。

请注意,我们没有直接增加aptr。如果我们这样做,aptr将不再指向内存缓冲区的启动,并且当我们释放缓冲区时程序会崩溃,因为它将在内存缓冲区之外的取消赋值内存。如果需要直接增加一个指针,那么创建一个临时指针变量并增加它,而不是在原始赋值中使用的指针。

内存缓冲区和指针是在内存中存储和操作数据的强大方式。必须注意,以确保您正在根据存储在缓冲区中的数据类型正确访问数据。