Share via


Unsafe C# with Pointers

Pointers are very fascinating things in C and C++. A pointer is a variable valued with the memory address another variable. They maintain a common rule, like a variable or constant we need to define a pointer in order to store the variable or constant's address. Pointers are very efficient, because we directly access to memory location with out code and much closer to the machine language. C# provides Pointer facility to us. But the limitation we have in C# pointers is we can hold only the memory address of value types and arrays. Sometimes this is an advantage because there is no real need of holding memory address of reference types as they might cause us deadlocks. We define pointers in C# as they are defined in C / C++ [type] *[variable-name]; for example, int *x; Let's see an example, where we declare an instance data int a = 15; then declare a pointer which holds the memory location of the instance data a. So the code goes like:

int a = 15;
int *pointer = &a;

Remember, the followings are also valid, the place of * really doesn't matter:

int a = 15;
int* pointer = &a;
int a = 15;
int * pointer = &a;

But to maintain the code quality and naming conventions we use int *pointer. Now lets make this example real and try to make a console application with this.

using System;

namespace TestPointer
{
    class Program
    {
        static void Main(string[] args)
        {
             int a = 15;
             int* pointer = &a;
             Console.WriteLine(a);
             Console.WriteLine((int)pointer);
             Console.ReadLine();
        }
    }
}

This will return a compile time error, saying:

https://programmium.files.wordpress.com/2015/04/first-error.png    

C# compiler never allows pointer operations by default, however using unsafe keywords we can define unsafe context where pointers can be used. So let's define it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
using System;

namespace TestPointer
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = 15;
            Console.WriteLine(a);
            unsafe
            {
                int* pointer = &a;
                Console.WriteLine((int)pointer);
            }
            Console.ReadLine();
        }
    }
}

Now you can see, from line 13 to 14 we are using pointers and we should define unsafe context for those two lines. It's not a good practice to make unsafe context for all code. Now if we want to run this code, we again get another error:

https://programmium.files.wordpress.com/2015/04/second-error.png

As mentioned above C# compiler does not allow unsafe codes, we have mentioned the compiler, that we have a unsafe part in our code by defining unsafe context now we have to instruct compiler to compile the code with unsafe. If you use csc.exe to compile the code with command prompt, you have to call csc.exe with /unsafe parameter. So if you want to compile code with command prompt, say, csc.exe /unsafe TestPointer.cs Or can use project properties, and under the "Build" tab of the project properties has "Allow Unsafe code"

https://programmium.files.wordpress.com/2015/04/allow-unsafe-code.png

If we run the above code after saving the project properties,

https://programmium.files.wordpress.com/2015/04/output.png

using fixed

Garbage collector automatically erase the instance variable a after it becomes unusable. Since objects in the memory are movable this makes garbage collection possible, but when we perform a pointer operation, the data should be in a fixed memory location, so we use fixed keyword. Remember you can't use local variables, value parameters, and variables created by dereferencing pointers under fixed context, as the location of the variable is already fixed (you can refer more here) Let's have a look at the example,

class Program
{
    unsafe static void Main(string[] args)
    {
        fixed (int * pointer = &Line.color)
        {
            Console.WriteLine((int)pointer);
        }

        Line line = new Line();
        fixed (int* pointer = &line.a)
        {
            Console.WriteLine((int)pointer);
        }

        Console.ReadLine();
    }
}

class Line
{
    public static int color;
    public int a;
}

But the below code will return a compile time error.

class Program
{
    unsafe static void Main(string[] args)
    {
        int a;
        fixed (int * pointer = &a)
        {
            Console.WriteLine((int)pointer);
        }

        Console.ReadLine();
    }
}

As we are using a already fixed variable.

Conclusion

Really there is no need for using pointers in C#, unless you are using an assembly from C++ that uses pointer. But as a programmer in C# you should know C# has the ability to perform pointer operation. Happy coding.