Home  |  Created on - November 2005


Using unsafe with pointers in C#

A lot of C programmers could not digest Java was because Java didn't let them manipulate pointers. Anyway C# supports pointers. You can use the unsafe keyword to inform the compiler that the following function or block is unsafe. And once you do that you can use pointers in that unsafe area.

using System;
class infosrama 
{
    unsafe static void Increment(int* p) 
    {
        //increment the int pointed to by p
        *p=*p+1;
    }

    public static void Main() 
    {
        int i = 1;
        //we pass the address of the int to the function as it expects a pointer
        unsafe 
        {
            Increment(&i);
        }
        //now we print out the value of i
        Console.WriteLine (i);
    }
}


			

When you run the program, you'll see 2 printed on screen. This is because you have passed the address of the variable i to the function Increment. Variable i is created on the stack. &i gives its address on the stack. Thus when within the function Increment, p is pointing to i's address. Thus when we add 1 to *p we are actually incrementing i

Program 2

using System;
class infosrama
{
    unsafe public static int Main()
    {
        int j=100;
        int k=100;
        Console.WriteLine("address of j={0} and address of k={1}",
				(int)&j,(int)&k);
        Console.WriteLine("j={0} k={1}",j,k);
        int *p;
        p=&j;
        Console.WriteLine("p now points to {0}",(int)p);
        *p=200;
        Console.WriteLine("j={0} k={1}",j,k);
        p=&k;
        Console.WriteLine("p now points to {0}",(int)p);
        *p=300;
        Console.WriteLine("j={0} k={1}",j,k);

        return 0;
    }	
}


		
		

When I ran it I got the below output. You would get something similar. The output will clearly give an idea of what's going on.

address of j=1244312 and address of k=1244308
j=100 k=100
p now points to 1244312
j=200 k=100
p now points to 1244308
j=200 k=300
	  

Program 3
Okay. In this final program I'll show you how to use pointers to manipulate a character string. In this program there is a function that takes a string and encodes or decodes it using XOR. If you pass a string to it it will encode it and if you pass the encoded string to it, it will decode it. Of course this is by no way a safe or practical encryption method. I am using it merely to demonstrate the use of pointers.

using System;
class infosrama
{
    public static void Main()
    {
        string s="Code Project is cool";
        Console.Write("the original string : ");
        Console.WriteLine("{0}\r\n",s);
		
        char[] b = new char[100];
        s.CopyTo(0,b,0,20);
		
        Console.Write("the encoded string : ");
        unsafe 
        {
            fixed(char *p=b)NEncodeDecode(p);
        }
        for(int t=0;t<20;t++)
            Console.Write(b[t]);
        Console.WriteLine("\r\n");
		
        Console.Write("the decoded string : ");
        unsafe 
        {
            fixed(char *p=b)NEncodeDecode(p);
        }
        for(int t=0;t<20;t++)
            Console.Write(b[t]);
        Console.WriteLine();
		
    }	
    unsafe public static void NEncodeDecode(char *s)
    {
        int w;
        for(int y=0;y<20;y++)
        {
            w=(int)*(s+y);
            w=w^5;
            *(s+y)=(char)w;
        }		
    }		
}


		

This is the output.

the original string : Code Project is cool

the encoded string : Fja`%Uwjo`fq%lv%fjji

the decoded string : Code Project is cool
		

You will notice a new keyword here called fixed. When you precede a statement or a function with fixed you are instructing  the .Net garbage collector not to relocate that variable till the statement or function has finished. The fixed keyword is only allowed in an unsafe context. If we don't use fixed there is little point in using pointers as the results would be unpredictable if the garbage collector keeps relocating the managed variables. Luckily the compiler won't let you point to managed variables unless you specify the fixed keyword.

In the function you can see that I use the expression *(s+y). s is the address pointing to the string. y is incremented starting from 0 and ending upto 19. Thus when I give *(s+y) I get the pointers to characters in those locations. Lets assume s points to 1000. Thus *(s) will give me the contents of location 1000. Now if I give *(s+1) I get the contents of 1002, and for *(s+2) I get 1004 and so on. The compiler knows I am pointing to a character array and thus each increment jumps 2 bytes as char is a 16 bit value. C# actually maps char to the .Net type System.Char.

Conclusion
Please be careful when writing unsafe code. Any small error, even a silly typing mistake, might crash your program randomly and unpredictably. The error might also be a rarely occurring one and thus harder to debug. But those of you who had used pointers in C/C++ and want to use them in C# may do so at their leisure.