Csharp/C Sharp/Language Basics/Unsafe Code

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

Accessing Structure Members with a Pointer

<source lang="csharp"> using System;

public struct Point2D {

   public int X;
   public int Y;

}

public class MyClass {

   public unsafe static void Main() {
       Point2D MyPoint;
       Point2D * PointerToMyPoint;
  
       MyPoint = new Point2D();
       PointerToMyPoint = &MyPoint;
       PointerToMyPoint->X = 100;
       PointerToMyPoint->Y = 200;
       Console.WriteLine("({0}, {1})", PointerToMyPoint->X, PointerToMyPoint->Y);
   }

}

      </source>


Address and size of pointer object

<source lang="csharp"> using System; class MainEntryPoint {

   static unsafe void Main() {
       int x = 10;
       short y = -1;
       byte y2 = 4;
       double z = 1.5;
       int* pX = &x;
       short* pY = &y;
       double* pZ = &z;
       Console.WriteLine("Address of x is 0x{0:X}, size is {1}, value is {2}",(uint)&x, sizeof(int), x);
       Console.WriteLine(
           "Address of y is 0x{0:X}, size is {1}, value is {2}",
           (uint)&y, sizeof(short), y);
       Console.WriteLine(
           "Address of y2 is 0x{0:X}, size is {1}, value is {2}",
           (uint)&y2, sizeof(byte), y2);
       Console.WriteLine(
           "Address of z is 0x{0:X}, size is {1}, value is {2}",
           (uint)&z, sizeof(double), z);
       Console.WriteLine(
           "Address of pX=&x is 0x{0:X}, size is {1}, value is 0x{2:X}",
           (uint)&pX, sizeof(int*), (uint)pX);
       Console.WriteLine(
           "Address of pY=&y is 0x{0:X}, size is {1}, value is 0x{2:X}",
           (uint)&pY, sizeof(short*), (uint)pY);
       Console.WriteLine(
           "Address of pZ=&z is 0x{0:X}, size is {1}, value is 0x{2:X}",
           (uint)&pZ, sizeof(double*), (uint)pZ);
       *pX = 20;
       Console.WriteLine("After setting *pX, x = {0}", x);
       Console.WriteLine("*pX = {0}", *pX);
       pZ = (double*)pX;
       Console.WriteLine("x treated as a double = {0}", *pZ);
       Console.ReadLine();
   }

}

</source>


Allocating Memory from the Stack

<source lang="csharp"> using System;

public class MyClass {

   public unsafe static void Main()
   {
       int * buf = stackalloc int [5];
  
       for(int i = 0; i < 5; i++)
           buf[i] = i;
       for(int i = 0; i < 5; i++)
           Console.WriteLine(buf[i]);
   }

}

      </source>


Fixing Managed Data in Memory

<source lang="csharp"> using System;

public class MyClass {

   public unsafe static void Main()
   {
       int i;
       int [] intArr;
  
       intArr = new int [5];
       fixed(int * IntegerPointer = intArr)
       {
           for(i = 0; i < 5; i++)
               IntegerPointer[i] = i;
       }
       for(i = 0; i < 5; i++)
           Console.WriteLine(intArr[i]);
   }

}

      </source>


Get variable address in unsafe mode

<source lang="csharp"> using System; public class MainEntryPoint {

   public static unsafe void Main() {
       Console.WriteLine("Size of Currency struct is " + sizeof(MyStruct));
       MyStruct amount1, amount2;
       MyStruct* pointerStruct = &amount1;
       long* pDollars = &(pointerStruct->Dollars);
       byte* pCents = &(pointerStruct->Cents);
       Console.WriteLine("Address of amount1 is 0x{0:X}", (uint)&amount1);
       Console.WriteLine("Address of amount2 is 0x{0:X}", (uint)&amount2);
       Console.WriteLine("Address of pAmt is 0x{0:X}", (uint)&pointerStruct);
       Console.WriteLine("Address of pDollars is 0x{0:X}", (uint)&pDollars);
       Console.WriteLine("Address of pCents is 0x{0:X}", (uint)&pCents);
       pointerStruct->Dollars = 20;
       *pCents = 50;
       Console.WriteLine("amount1 contains " + amount1);
       --pointerStruct;   
       Console.WriteLine("amount2 has address 0x{0:X} and contains {1}",
          (uint)pointerStruct, *pointerStruct);
       MyStruct* pTempCurrency = (MyStruct*)pCents;
       pCents = (byte*)(--pTempCurrency);
       Console.WriteLine("Address of pCents is now 0x{0:X}", (uint)&pCents);
       Console.WriteLine("\nNow with classes");
       MyClass amount3 = new MyClass();
       fixed (long* pDollars2 = &(amount3.Dollars))
       fixed (byte* pCents2 = &(amount3.Cents)) {
           Console.WriteLine("amount3.Dollars has address 0x{0:X}", (uint)pDollars2);
           Console.WriteLine("amount3.Cents has address 0x{0:X}", (uint)pCents2);
           *pDollars2 = -100;
           Console.WriteLine("amount3 contains " + amount3);
       }
   }

} struct MyStruct {

   public long Dollars;
   public byte Cents;
   public override string ToString() {
       return "$" + Dollars + "." + Cents;
   }

} class MyClass {

   public long Dollars;
   public byte Cents;
   public override string ToString() {
       return "$" + Dollars + "." + Cents;
   }

}

</source>


int pointer variable

<source lang="csharp"> using System; public class MainClass {

   static void Main(string[] args) {
       unsafe {
           int variable = 10;
           int* pVariable = &variable;
           Console.WriteLine("Value at address is {0}.", *pVariable);
       }
   }

}

</source>


mark method as unsafe

<source lang="csharp"> class FixedArrayApp {

   unsafe public static void Foo(int* pa)
   {
       for (int* ip = pa; ip < (pa+5); ip++)
       {
           Console.Write("{0,-3}", *ip);
       }
   }
  
   static void Main(string[] args)
   {
       int[] ia = new int[5]{12,34,56,78,90};
  
       unsafe
       {
           fixed (int* pa = ia)
           {
               Foo(pa);
           }
       }
   }

}

</source>


object pointer

<source lang="csharp"> using System; public struct MyValue {

   public int id;
   private decimal price;
   public MyValue(int id, decimal price) 
   { 
       this.id = id; 
       this.price = price;
   }
   public void Foo() { Console.WriteLine("Foo"); }

}

class DerefMemberApp {

   static void Main(string[] args)
   {
       MyValue i = new MyValue(123, 45.67m);
  
       unsafe
       {
           MyValue* pi = &i;
           (*pi).Foo();
           pi->Foo();
  
           Console.WriteLine("id = {0}", pi->id);
       }
   }

}

</source>


Supported sizeof() Types

<source lang="csharp">

Expression Result sizeof(sbyte) 1 sizeof(byte) 1 sizeof(short) 2 sizeof(ushort) 2 sizeof(int) 4 sizeof(uint) 4 sizeof(long) 8 sizeof(ulong) 8 sizeof(char) 2 sizeof(float) 4 sizeof(double) 8 sizeof(bool) 1

      </source>


unsafe and fixed block

<source lang="csharp"> public class MyValue {

   public int id;
   public MyValue(int id) { this.id = id; }

}

class UnsafeClassApp {

   unsafe public static void Swap(int* pi, int* pj)
   {
       int tmp = *pi;
       *pi = *pj;
       *pj = tmp;
   }
  
   static void Main(string[] args)
   {
       MyValue i = new MyValue(123);
       MyValue j = new MyValue(456);
       Console.WriteLine("Before Swap:\ti = {0}, j = {1}", i.id, j.id);
  
       unsafe
       {
            (int* pi = &i.id, pj = &j.id)
           {
               Swap(pi, pj);
           }
       }
  
       Console.WriteLine(
           "After Swap:\ti = {0}, j = {1}", i.id, j.id);
   }

}

</source>


Unsafe code: get data type size

<source lang="csharp">

  using System;
  class MainEntryPoint
  {
     static unsafe void Main()
     {
        int x=100;
        short y = -19;
        byte y2 = 45;
        double z = 31.5;
        int *pX = &x;
        short *pY = &y;
        double *pZ = &z;
        Console.WriteLine("Address of x is 0x{0:X}, size is {1}, value is {2}", (uint)&x, sizeof(int), x);
        Console.WriteLine("Address of y is 0x{0:X}, size is {1}, value is {2}", (uint)&y, sizeof(short), y);
        Console.WriteLine("Address of y2 is 0x{0:X}, size is {1}, value is {2}",(uint)&y2, sizeof(byte), y2);
        Console.WriteLine("Address of z is 0x{0:X}, size is {1}, value is {2}", (uint)&z, sizeof(double), z);
        Console.WriteLine("Address of pX=&x is 0x{0:X}, size is {1}, value is 0x{2:X}",(uint)&pX, sizeof(int*), (uint)pX);
        Console.WriteLine("Address of pY=&y is 0x{0:X}, size is {1}, value is 0x{2:X}",(uint)&pY, sizeof(short*), (uint)pY);
        Console.WriteLine("Address of pZ=&z is 0x{0:X}, size is {1}, value is 0x{2:X}",(uint)&pZ, sizeof(double*), (uint)pZ);
        *pX = 20;
        Console.WriteLine("After setting *pX, x = {0}", x);
        Console.WriteLine("*pX = {0}", *pX);
        pZ = (double*)pX;
        Console.WriteLine("x treated as a double = {0}", *pZ);
     }
  }


      </source>


Unsafe Methods

<source lang="csharp">

using System;

public class MyClass {

   public unsafe static void Main()
   {
       int MyInteger = 123;
       int * MyIntegerPointer = &MyInteger;
  
       Console.WriteLine(*MyIntegerPointer);
   }

}

      </source>


Use unsafe method to clone array

<source lang="csharp"> public struct MyValue {

   public int id;
   public MyValue(int id) { this.id = id; }

} class ClassAddressApp {

   unsafe public static MyValue[] CloneMyValues(MyValue[] box)
   {
       MyValue[] ret = new MyValue[box.Length];
       fixed (MyValue* src = box, dest = ret)
       {
           MyValue* pSrc = src;
           MyValue* pDest = dest;
           for (int index = 0; index < box.Length; index++)
           {
               *pDest = *pSrc;
               pSrc++;
               pDest++;
           }
       }
       return ret;
   }
  
   static void Main(string[] args)
   {
       MyValue[] box = new MyValue[2];
       box[0] =  new MyValue(1);
       box[1] = new MyValue(2);
  
       MyValue[] bag = CloneMyValues(box);
       foreach (MyValue i in bag)
       {
           Console.WriteLine(i.id);
       }
   }

}

</source>


Use unsage code to swap two integers

<source lang="csharp">

public class TestUnsafeApp {

   unsafe public static void Swap(int* pi, int* pj)
   {
       int tmp = *pi;
       *pi = *pj;
       *pj = tmp;
   }
  
   public static void Main(string[] args)
   {
       int i = 3;
       int j = 4;
       Console.WriteLine("BEFORE: i = {0}, j = {1}", i, j);
  
       unsafe { Swap(&i, &j); }
  
       Console.WriteLine("AFTER:  i = {0}, j = {1}", i, j);
   }

}

</source>


Using the unsafe keyword

<source lang="csharp"> using System; class Test {

 public static unsafe String UnsafeCodeExample( String s ) {
   int strLength = s.Length;
   char[] str = new char[strLength+1];
   string strReturn = "";
   fixed(char* strPointer = str) {
     for ( int i=0; i<strLength; ++i )
       strReturn += strPointer[i];
   }
   return strReturn;
 }
 public static void Main() {
  String s = UnsafeCodeExample("This is a test");
  Console.WriteLine( "Reversed: {0}", s );
 }

}

      </source>