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:
Yorum Gönder