ARTICLE

Using pointers in VB

Posted by Phil Curnow Articles | Visual Basic 2010 April 29, 2008
This article explains the concept of pointers and how you implement them in VB should you need to.
 
Reader Level:

Back in the late 1980's and up to around 1997, most of my development work was done using the C programming language. Anyone who has done a fair amount of work in C or C++ would not have been able to avoid the use of pointers. Recently I had to re-visit some old code I had written in C and one of my first comments was 'wow pointers, I remember them!'

I have known since I started using VB.net (and that's been a few years) that you could use pointers, but to be honest, I have never had to use them and have never gone looking for a reason to use them. The main reasons I have written this article is to introduce the concept of pointers to any developers who have not seen them before, and as a little nostalgic trip back to the days when they were part of my daily coding diet!

So, what is a Pointer?

A pointer is nothing more than a variable that holds the address in memory of another variable. In VB, pointers can only be used on value types and arrays. As a structure is a value type, pointers can be used with them, but there is one caveat with this, the structure must not contain any reference types if you plan to use pointers. Any of the following may be a pointer:

  • Sbyte
  • byte
  • short
  • ushort
  • int
  • uint
  • long 
  • ulong 
  • char 
  • float 
  • double 
  • decimal 
  • bool

unsafe keyword

Typically when we write code in VB by default it is what's known as safe code. Unsafe code allows you to manipulate memory directly, in the normal world of VB and the .NET Framework, this is seen as potentially dangerous, and as such you have to mark your code as unsafe. Using unsafe code, you are loosing garbage collection and whilst directly accessing memory, you have the possibility of accessing memory that you didn't want to and causing untold problems with your application. Unsafe code can only be used within a fully trusted assembly.

Now it is time to write some program code to demonstrate the use of pointers. Consider the following code.

Private Shared Sub Main(ByVal args As String())

    Dim age As Integer = 32

    Console.WriteLine("age = {0}", age)

End Sub

A very simple piece of code that will print age = 32 on the console. Now let's introduce a pointer into the mix. When we declare a pointer, we have to declare it in a certain way, this being type* variable; the asterisk (dereferencer symbol) informs the compiler that we are declaring a pointer variable, the type says that we intend to use a pointer to store the address of type type. So using our simple piece of code above, let's creates an integer pointer to point to age.

Private Shared Sub Main(ByVal args As String())

    Dim age As Integer = 32

    Dim age_ptr As Integer*

    Console.WriteLine("age = {0}", age)

End Sub

Notice the use of the unsafe keyword, if we had not enclosed our code within unsafe, we would have received the following compilation error.

Pointers and fixed sized buffers may only be used in an unsafe context.

We could have declared the whole method as unsafe and this would have worked fine, for example:

unsafe static Sub Main(ByVal args As String())

So, what can we do with our pointer? As stated at the beginning of the article, pointers hold addresses in memory to other variables, so we need to make age_ptr point to the memory location of age. To do this, we use the following line of code:

age_ptr = &age;

The ampersand '&' is the referencer and means the 'location of'. So if we now do the following in our code:

Private Shared Sub Main(ByVal args As String())

    Dim age As Integer = 32

    Dim age_ptr As Integer*

    age_ptr = AddressOf age

    Console.WriteLine("age = {0}", age)

    Console.WriteLine("age_ptr = {0}", *)

End Sub

We should now see the following output on the console:

age = 32
age_ptr = 32

Basically, with the display line for age_ptr, we are printing the value held in the memory location that age_ptr is pointing to (in this instance, the age variable).

Now, what happens if we add the following to the example?

*age_ptr += 3;

Console.WriteLine("age now = {0}", age);


What do you think the output will be (note that we are printing the value of age)? If you have said 35 you are correct! The value of age has been changed to 35. Let's dissect the line *age_ptr += 3 and see what's happening.

 

age_ptr has been declared as an integer, the term *age_ptr can be read as 'the integer value at the memory location age_ptr is pointing to'. We are then simply adding 3 to the integer value, giving us a result of 35. As age_ptr is pointing to the memory location where age stores its value, essentially we have modified the variable age.


Pointers to Structures


As previously mentioned, you can define a pointer to a structure, but you have to make sure that there are no reference types in the structure, for example, consider the example code below:

 

Class TestClass

    ..........

End Class

Structure TestStruct

    Public age As Integer

    Public test As TestClass

End Structure


You would not be able to then do the following:


TStruct test_struct;
TStruct* struct_ptr;
struct_ptr = &test_struct;


When compiling this code, you would receive the error message:


Cannot take the address of, get the size of, or declare a pointer to a managed type.

 

So let's create a valid structure and see how we use a pointer to the structure. Our structure will be a simple one that contains two integers X and Y to simulate co-ordinates on a screen.

 

Structure Location

    Public X As Integer

    Public Y As Integer

End Structure


Now we can create the following code:

 

Private Shared Sub Main(ByVal args As String())

    Dim loc As Location

    loc.X = 100

    loc.Y = 100

 

    Dim loc_ptr As Location*

    loc_ptr = AddressOf

End Sub

 

There should be no surprises in the code above. loc_ptr is of the type Location, which is our structure. So how do we use our pointer? To access the X and Y members of our structure through the use of our pointer, we can use the following syntax


(*loc_ptr).X;  or  loc_ptr->X;


I know which one I would rather use (the second option), but both perform exactly the same function. So if we wanted to display and modify X we can do this as follows:

 

Private Shared Sub Main(ByVal args As String())

    Dim loc As Location

    loc.X = 100

    loc.Y = 100

 

    Dim loc_ptr As Location*

    loc_ptr = AddressOf

    Console.WriteLine("X = {0}", )

 

    loc_ptr->X = 200

    Console.WriteLine("X = {0}", )

End Sub


Pointers and Classes


A class is a reference type, so therefore you cannot define a pointer to a class, but you can define a pointer to a class member that is a value type. Before we see an example of how to do this, there is something that you need to understand before creating pointers to value type members of a class.


When using safe code, the garbage collector will possibly move an object in memory during its lifetime, this is done to manage free resources and stop fragmentation. If you have a pointer to a value type in a class, this could cause some unexpected results, and some headaches! Needless to say, there is a way around this problem. We can instruct the garbage collector not to move specific objects. We do this by using the fixed keyword. Let's take a look at an example.


The design of the following class is not ideal and any OO design guru's out there will probably be shaking their heads at it, but it has been done as a very simple example.


For Example

 

Class PTest

    Public Sub New()

    End Sub

    Public age As Integer

    Public Sub DisplayAge()

        Console.WriteLine("age = {0}", age)

    End Sub

End Class


And some example code to create an instance of the class and then manipulate the public variable age using a pointer.

 

Private Shared Sub Main(ByVal args As String())

    Dim p As New PTest()

    p.age = 32

    p.DisplayAge()

    fixed (int* age = &p.age)

    *age += 3

    p.DisplayAge()

End Sub


Notice the use of the keyword fixed. Basically what this is ensuring is that during the execution of the code within the fixed statement, the object p will not be moved, thus solving the problem of our pointer pointing to an invalid memory location, this operation is called 'pinning'.


Compilation of unsafe code


In order to compile program code that contains unsafe code, you need to inform the compiler. When using the command line compiler, you need to issue the /unsafe switch. When using Visual Studio, you need to tick the box in the project properties titled Allow Unsafe code (this is found within the Build section).


Conclusion


Using pointers in VB is almost never required and they are generally only used in conjunction with P/Invoke. If you have a requirement to use pointers, you need to be very careful as you are manipulating memory directly.


My advice would be, don't go looking for a reason to use them, if you can perform your task using safe code, do so.

NOTE: THIS ARTICLE IS CONVERTED FROM C# TO VB.NET USING A CONVERSION TOOL. ORIGINAL ARTICLE CAN BE FOUND ON C# Corner (http://www.c-sharpcorner.com/).

Login to add your contents and source code to this article
share this article :
post comment
 
Nevron Diagram
Become a Sponsor
PREMIUM SPONSORS
  • The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
    The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
Nevron Diagram
Become a Sponsor