25 Ağustos 2008 Pazartesi

C# Dinamic Memory Allocation

The keyword unsafe is used while dealing with pointer, the name reflects the risks that you might face while using them. Let’s see where to place it.

We can declare a whole class as unsafe:

unsafe class Class1

{

//you can use pointers here!

}

Or only some class members can be declared as unsafe:

class Class1

{

//pointer

unsafe int * ptr;

unsafe void MyMethod()

{

//you can use pointers here

}

}

The same applies to other members such as the constructor and the properties.

To declare unsafe local variables in a method, you have to put them in unsafe blocks as the following:

static void Main()

{

//can't use pointers here

unsafe

{

//here you can declare and use pointer

}

//can't use pointers here

}

You can’t declare local variables the same way we used in declaring global variables, to use pointers, and next we will use the operator sizeof, in a “safe” method. We have to put them in an unsafe block.

static void Main()

{

unsafe int * ptri; //Wrong

}

If you got too excited and tried to use unsafe then when you compile the code just by using

csc test.cs

You will experience the following error:

error CS0227: Unsafe code may only appear if compiling with /unsafe

For compiling unsafe code use the /unsafe

csc test.cs /unsafe

In VS.NET go to the project property page and in “configuration properties>build” set Allow Unsafe Code Blocks to True.

After we knew how to declare a block as unsafe we should now learn how to declare and use pointers in it.

Declaring pointers

To declare a pointer of any type all what you have to do is to put ‘*’ after the type name such as

int * ptri;

double * ptrd;

NOTE: If you used to use pointer in C or C++ then be careful that in C# int * ptri, i; ‘*’ applies to the type itself not the variable so ‘i’ is a pointer here, same as arrays.

Using pointers

Using pointers can be demonstrated in the following example:

static void Main()

{

int var1 = 5;

unsafe

{

int * ptr1, ptr2;

ptr1 = &var1;

ptr2 = ptr1;

*ptr2 = 20;

}

Console.WriteLine(var1);

}

The operator ‘&’ means “address of”, so ptr1 will hold the address of var1, ptr2 = ptr1 will assign the address of var1, which ptr1 was holding, to ptr2. Using ‘*’ before the pointer name means “the contain of the address”, so 20 will be written where ptr2 points.

Now var1 value is 20.

sizeof operator

As the name says, sizeof operator will return the number of bytes occupied of the given data type (could also be used for classes and structs, we will see that in part 2)

i.e.

unsafe

{

Console.WriteLine("sbyte: {0}", sizeof(sbyte));

Console.WriteLine("byte: {0}", sizeof(byte));

Console.WriteLine("short: {0}", sizeof(short));

Console.WriteLine("ushort: {0}", sizeof(ushort));

Console.WriteLine("int: {0}", sizeof(int));

Console.WriteLine("uint: {0}", sizeof(uint));

Console.WriteLine("long: {0}", sizeof(long));

Console.WriteLine("ulong: {0}", sizeof(ulong));

Console.WriteLine("char: {0}", sizeof(char));

Console.WriteLine("float: {0}", sizeof(float));

Console.WriteLine("double: {0}", sizeof(double));

Console.WriteLine("decimal: {0}", sizeof(decimal));

Console.WriteLine("bool: {0}", sizeof(bool));

//did i miss something?!

}

the output will be:

sbyte: 1

byte: 1

short: 2

ushort: 2

int: 4

uint: 4

long: 8

ulong: 8

char: 2

float: 4

double: 8

decimal: 16

bool: 1

Great, we don’t have to remember the size of every data type anymore!

That’s it for part one, in the second part I will cover the following subjects:

  • Casting pointers
  • Pointer arithmetic
  • Pointers to classes and structs
  • Optimizing performance by using pointers

Hiç yorum yok: