Using Unsafe Code and Pointers in C#

Introduction

One of the biggest features of the .NET platform is the support for type safety. This means that the Common Language Runtime – the engine of .NET - guarantees that there will not be any type errors  (issues which generally arise because of discrepancy between different data types for an application’s constants, variables and methods).

The benefits of type safety include:

  • Illegal operations are avoided.
  • No wild pointers – a pointer of one type is considered as pointer of other type
  • Avoiding buffer overflow

However, there are certain cases where you need access to code to unsafe code – code for which there is no guarantee of type security, e.g. pointers, or calling native APIs (DLLImport).

Any method, type or code block can be defined as unsafe using the unsafe C# keyword.

To compile the code, we need to use the “/unsafe” compiler flag.

Caveat: Tagging your code as unsafe can result in security risks in your code.

The Pointer Basics

In unsafe code, you can declare a type to be a pointer type.

The declaration is shown below:

type* typename;

For example, to declare a pointer to an int, we would declare it as:

int* ptr_MyVal;

If you want to declare multiple pointer types, we declare them as:

int* ptr_MyVal1, ptr_MyVal2;

Pointers can be declared for:

  • all scalar types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal and bool.
  • Enum types
  • Pointer types (pointers to pointers) (type**) - e.g. int**
  • User-defined structs

Let us take a look at a simple C# application to do some pointer arithmetic.

We will create a pointer and use the pointer to add a number to the pointee.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace PointersDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            int valueToBeOperated = 10;
            unsafe
            {
                int* ptr_value = &valueToBeOperated;
                Console.WriteLine("valueToBeOperate = " + valueToBeOperated);
                Console.WriteLine("valueToBeOperate via pointer = " +  *ptr_value);
                *ptr_value += 10;
                Console.WriteLine("valueToBeOperate = " + valueToBeOperated);
                Console.WriteLine("valueToBeOperate via pointer = " + *ptr_value);
            }
 
        }
    }
}

In the above listing, we are declaring a pointer to an int and then using the pointer reference to add 10 and then print the output.

To do this, you will have to do two things.

First, the code, which uses pointers will need to be declared in an unsafe context (see the highlighted section).

Next, we need to declare to the compiler  that we want to compile unsafe code. In Visual Studio, we can do it by changing the Project Properties.

Allow Unsafe Code
Allow Unsafe Code

This signals to the compiler to pass the “/unsafe”  flag to the csc.exe compiler.

The output of the above code is:

valueToBeOperate = 10
valueToBeOperate via pointer = 10
valueToBeOperate = 20
valueToBeOperate via pointer = 20

Next, we can take an advanced look to pointers.

In our second case, we will look at pointers to an array.

When we need pointers to objects in the heap, we need to use the fixed keyword to annotate the pointer, to indicate to the compiler that the objects must be fixed to avoid changing the location the pointer is referencing. This results in the object not moving when memory management operations are done.

// Listing 2- Array pointers

int[] myArray = new int[5] { 1, 2, 3, 4, 5 };

                fixed (int* ptr_array = &myArray[0])

                {

                    int* ptr_ptr = ptr_array; // pointer to a pointer

                    Console.WriteLine("*ptr_array = " + *ptr_array);

                    Console.WriteLine("**ptr_ptr = " + *ptr_ptr);

                    *ptr_array += 10;

                    Console.WriteLine("*ptr_array = " + *ptr_array);

                    Console.WriteLine("**ptr_ptr = " + *ptr_ptr);

                    ptr_ptr++;

                    Console.WriteLine("*ptr_array (does not change) = " + *ptr_array);

                    Console.WriteLine("**ptr_ptr (changes to the next array element) = " + *ptr_ptr);

                }

In the above snippet, we declare a pointer to an array, ptr_array. Notice that we need to decorate it with the fixed keyword (highlighted).

When we add 10 to *ptr_array, we are actually dereferencing to the first element and adding 10.

When we increment ptr_ptr (pointer to the pointer to the array), we are telling the pointer to move to the next array element.

The output of the above snippet is:

*ptr_array = 1
**ptr_ptr = 1
*ptr_array = 11
**ptr_ptr = 11
*ptr_array (does not change) = 11
**ptr_ptr (changes to the next array element) = 2

The complete listing of the above code including a working Visual Studio 2013 project is available at PointersDemo

.

Summary

In this article, we learned about using unsafe code and pointers in C#. I hope you have found this information useful.

About the Author

Vipul Patel is a Program Manager currently working at Amazon Corporation. He has formerly worked at Microsoft in the Lync team and in the .NET team (in the Base Class libraries and the Debugging and Profiling team). He can be reached at vipul.patel@hotmail.com



Related Articles

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • U.S. companies are desperately trying to recruit and hire skilled software engineers and developers, but there is simply not enough quality talent to go around. Tiempo Development is a nearshore software development company. Our headquarters are in AZ, but we are a pioneer and leader in outsourcing to Mexico, based on our three software development centers there. We have a proven process and we are experts at providing our customers with powerful solutions. We transform ideas into reality.

  • Lenovo recommends Windows 8 Pro. "I dropped my laptop getting out of the taxi." This probably sounds familiar to most IT professionals. If your employees are traveling, you know their devices are in for a rough go. Whether it's a trip to the conference room or a convention out of town, any time equipment leaves a user's desk it is at risk of being put into harm's way. Stay connected at all times, whether at the office or on the go, with agile, durable, and flexible devices like the Lenovo® …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date