Csharp/C Sharp/Language Basics/Pointer Unsafe

Материал из .Net Framework эксперт
Версия от 14:39, 26 мая 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

An array name with an index yields a pointer to the start of the array

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

/* An array name with an index yields a pointer to the

  start of the array. */ 

using System;

public class PtrArray {

 unsafe public static void Main() { 
   int[] nums = new int[10]; 

   fixed(int* p = &nums[0], p2 = nums) { 
     if(p == p2) 
       Console.WriteLine("p and p2 point to same address."); 
   } 
 } 

}


      </source>


Demonstrate fixed

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

// Demonstrate fixed.

using System;

class Test {

 public int num; 
 public Test(int i) { num = i; } 

}

public class FixedCode {

 // mark Main as unsafe 
 unsafe public static void Main() { 
   Test o = new Test(19); 

   fixed (int* p = &o.num) { // use fixed to put address of o.num into p 

     Console.WriteLine("Initial value of o.num is " + *p); 
  
     *p = 10; // assign the to count via p 
    
     Console.WriteLine("New value of o.num is " + *p); 
   } 
 } 

}


      </source>


Demonstrate pointer comparison

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

// Demonstrate pointer comparison.

using System;

public class PtrCompDemo {

 unsafe public static void Main() { 

   int[] nums = new int[11]; 
   int x; 

   // find the middle 
   fixed (int* start = &nums[0]) {  
     fixed(int* end = &nums[nums.Length-1]) {  
       for(x=0; start+x <= end-x; x++) ; 
     } 
   } 
   Console.WriteLine("Middle element is " + x); 
 } 

}


      </source>


Demonstrate pointers and unsafe

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

// Demonstrate pointers and unsafe.

using System;

public class UnsafeCode {

 // mark Main as unsafe 
 unsafe public static void Main() { 
   int count = 99; 
   int* p; // create an int pointer 

   p = &count; // put address of count into p 

   Console.WriteLine("Initial value of count is " + *p); 

   *p = 10; // assign the to count via p 
    
   Console.WriteLine("New value of count is " + *p); 
 } 

}


      </source>


Demonstrate the effects of pointer arithmethic

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

// Demonstrate the effects of pointer arithmethic.

using System;

public class PtrArithDemo {

 unsafe public static void Main() { 
   int x; 
   int i;  
   double d; 

   int* ip = &i; 
   double* fp = &d; 

   Console.WriteLine("int     double\n"); 

   for(x=0; x < 10; x++) { 
      Console.WriteLine((uint) (ip) + " " + 
                        (uint) (fp)); 
      ip++; 
      fp++; 
   } 
 } 

}


      </source>


Index a pointer as if it were an array

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

// Index a pointer as if it were an array.

using System;

public class PtrIndexDemo {

 unsafe public static void Main() { 
   int[] nums = new int[10]; 

   // index pointer 
   Console.WriteLine("Index pointer like array."); 
   fixed (int* p = nums) { 
     for(int i=0; i < 10; i++)  
       p[i] = i; // index pointer like array 

     for(int i=0; i < 10; i++)  
       Console.WriteLine("p[{0}]: {1} ", i, p[i]); 
   } 

   // use pointer arithmetic 
   Console.WriteLine("\nUse pointer arithmetic."); 
   fixed (int* p = nums) { 
     for(int i=0; i < 10; i++)  
       *(p+i) = i; // use pointer arithmetic 

     for(int i=0; i < 10; i++)  
       Console.WriteLine("*(p+{0}): {1} ", i, *(p+i)); 
   } 
 } 

}


      </source>


Multiple Indirect

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

using System;

public class MultipleIndirect {

 unsafe public static void Main() { 
   int x;    // holds a int value  
   int* p;  // holds an int pointer 
   int** q; // holds an pointer to an int pointer 

   x = 10; 
   p = &x; // put address of x into p 
   q = &p; // put address of p into q 

   Console.WriteLine(**q); // display the value of x  
 } 

}


      </source>


Pointers and Declarative Pinning

<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3

  • /

// 31 - Interop\Calling Native DLL Functions\Pointers and Declarative Pinning // copyright 2000 Eric Gunnerson // file=ReadFileUnsafe.cs // compile with: csc /unsafe ReadFileUnsafe.cs using System; using System.Runtime.InteropServices; using System.Text; class FileRead {

   const uint GENERIC_READ = 0x80000000;
   const uint OPEN_EXISTING = 3;
   int handle;
   
   public FileRead(string filename)
   {
       // opens the existing file
       handle = CreateFile(    filename,
       GENERIC_READ,
       0, 
       0,
       OPEN_EXISTING,
       0,
       0);
   }
   
   [DllImport("kernel32", SetLastError=true)]
   static extern int CreateFile(
   string filename,
   uint desiredAccess,
   uint shareMode,
   uint attributes,        // really SecurityAttributes pointer
   uint creationDisposition,
   uint flagsAndAttributes,
   uint templateFile);
   
   [DllImport("kernel32", SetLastError=true)]
   static extern unsafe bool ReadFile(
   int hFile,
   void* lpBuffer, 
   int nBytesToRead,
   int* nBytesRead,
   int overlapped);
   
   public unsafe int Read(byte[] buffer, int count)
   {
       int n = 0;
       fixed (byte* p = buffer) 
       {
           ReadFile(handle, p, count, &n, 0);
       }
       return n;
   }

} public class PointersandDeclarativePinning {

   public static void Main(string[] args)
   {
       FileRead fr = new FileRead(args[0]);
       
       byte[] buffer = new byte[128];
       ASCIIEncoding e = new ASCIIEncoding();
       
       // loop through, read until done
       Console.WriteLine("Contents");
       while (fr.Read(buffer, 128) != 0)
       {
           Console.Write("{0}", e.GetString(buffer));
       }
   }

}

      </source>


References and Pointers

<source lang="csharp"> /*

* C# Programmers Pocket Consultant
* Author: Gregory S. MacBeth
* Email: gmacbeth@comporium.net
* Create Date: June 27, 2003
* Last Modified Date:
*/

using System; using System.Runtime.InteropServices; namespace Client.Chapter_7___References__Pointers_and_Memory_Management {

 public class ReferencesandPointers
 {
   static void Main(string[] args)
   {
     UsePointers();
   }
   static unsafe public void UsePointers()
   {
     char * pMyArray = (char*)Marshal.AllocCoTaskMem(6);
     while (*pMyArray != "\0")
     {
       Console.WriteLine(*pMyArray);
       pMyArray++;
     }
     Marshal.FreeCoTaskMem((IntPtr)pMyArray);
   }
 }

}

      </source>


Unsafe code: copy

<source lang="csharp"> /* C# Programming Tips & Techniques by Charles Wright, Kris Jamsa Publisher: Osborne/McGraw-Hill (December 28, 2001) ISBN: 0072193794

  • /

namespace nsType {

   using System;
   
   public class IntCopy
   {
       public static void Main ()
       {
           int [] arr1 = new int[] {1, 4, 2, 8, 5, 7};
           int [] arr2 = new int[arr1.Length];
           MemCpy (arr2, arr1, arr1.Length);
           arr1[0] = 142857;
           for (int x = 0; x < arr1.Length; ++x)
           {
               Console.Write ("arr1[{0}] = {1}\t", x, arr1[x]);
               Console.Write ("arr2[{0}] = {1}\n", x, arr2[x]);
           }
       }
       static unsafe public void MemCpy (int [] dst, int [] src, int size)
       {
           if ((size > dst.Length) || (size > src.Length))
           {
               ArgumentException e = new ArgumentException("The size argument is too large for one of the array arguments");
               throw (e);
           }
           fixed (int *Src = src, Dst = dst)
           {
               int* pSrc = Src;
               int* pDst = Dst;
               for (int n = 0; n < size; ++n)
               {
                   *pDst++ = *pSrc++;
               }
           }
       }
   }

}


      </source>


Unsafe Context

<source lang="csharp"> /* A Programmer"s Introduction to C# (Second Edition) by Eric Gunnerson Publisher: Apress L.P. ISBN: 1-893115-62-3

  • /

// 36 - Deeper into C#\Unsafe Context // copyright 2000 Eric Gunnerson // file=unsafe.cs // compile with: csc /unsafe /o+ unsafe.cs using System; using System.Diagnostics; using System.Runtime.InteropServices;

public class UnsafeContext {

   const int iterations = 20000;    // # to do copy
   const int points = 1000;        // # of points in array
   const int retryCount = 5;        // # of times to retry
   
   public delegate Point[] CloneFunction(Point[] a);
   
   public static void TimeFunction(Point[] arr, 
   CloneFunction func, string label)
   {
       Point[]    arrCopy = null;
       long start;
       long delta;
       double min = 5000.0d;    // big number;
       
       // do the whole copy retryCount times, find fastest time
       for (int retry = 0; retry < retryCount; retry++)
       {
           start = Counter.Value;
           for (int iterate = 0; iterate < iterations; iterate++)
           arrCopy = func(arr);
           delta = Counter.Value - start;
           double result = (double) delta / Counter.Frequency;
           if (result < min)
           min = result;
       }
   Console.WriteLine("{0}: {1:F3} seconds", label, min);
   }
   
   public static void Main()
   {
       Console.WriteLine("Points, Iterations: {0} {1}", points, iterations);
       Point[] arr = new Point[points];
       for (int index = 0; index < points; index++)
       arr[index] = new Point(3, 5);
       
       TimeFunction(arr, 
       new CloneFunction(Point.ClonePointArrayMemcpy), "Memcpy");
       TimeFunction(arr, 
       new CloneFunction(Point.ClonePointArrayUnsafe), "Unsafe");
       TimeFunction(arr, 
       new CloneFunction(Point.ClonePointArray), "Baseline");
   }

} class Counter {

   public static long Frequency 
   {
       get 
       {
           long freq = 0;
           QueryPerformanceFrequency(ref freq);
           return freq;
       }
   }
   public static long Value 
   {
       get 
       {
           long count = 0;
           QueryPerformanceCounter(ref count);
           return count;
       }
   }
   
   [System.Runtime.InteropServices.DllImport("KERNEL32",
   CharSet=System.Runtime.InteropServices.CharSet.Auto)]
   private static extern bool QueryPerformanceCounter(  ref long lpPerformanceCount);
   
   [System.Runtime.InteropServices.DllImport("KERNEL32", 
   CharSet=System.Runtime.InteropServices.CharSet.Auto)]
   private static extern bool QueryPerformanceFrequency( ref long lpFrequency);                     

} public struct Point {

   public Point(int x, int y)
   {
       this.x = x;
       this.y = y;
   }
   
   // safe version
   public static Point[] ClonePointArray(Point[] a)
   {
       Point[] ret = new Point[a.Length];
       
       for (int index = 0; index < a.Length; index++)
       ret[index] = a[index];
       
       return(ret);
   }
   
   // unsafe version using pointer arithmetic
   unsafe public static Point[] ClonePointArrayUnsafe(Point[] a)
   {
       Point[] ret = new Point[a.Length];
       
       // a and ret are pinned; they cannot be moved by
       // the garbage collector inside the fixed block.
       fixed (Point* src = a, dest = ret)
       {
           Point*    pSrc = src;
           Point*    pDest = dest;
           for (int index = 0; index < a.Length; index++)
           {
               *pDest = *pSrc;
               pSrc++;
               pDest++;
           }
       }
       
       return(ret);
   }
   // import CopyMemory from kernel32
   [DllImport("kernel32.dll")]
   unsafe public static extern void 
   CopyMemory(void* dest, void* src, int length);
   
   // unsafe version calling CopyMemory()
   unsafe public static Point[] ClonePointArrayMemcpy(Point[] a)
   {
       Point[] ret = new Point[a.Length];
       
       fixed (Point* src = a, dest = ret)
       {
           CopyMemory(dest, src, a.Length * sizeof(Point));
       }
       
       return(ret);
   }
   
   public override string ToString()
   {
       return(String.Format("({0}, {1})", x, y));
   }
   
   int x;
   int y;

}


      </source>


Use fixed to get a pointer to the start of a string

<source lang="csharp"> /* C#: The Complete Reference by Herbert Schildt Publisher: Osborne/McGraw-Hill (March 8, 2002) ISBN: 0072134852

  • /

// Use fixed to get a pointer to the start of a string.

using System;

public class FixedString {

 unsafe public static void Main() { 
   string str = "this is a test"; 

   // Point p to start of str. 
   fixed(char* p = str) { 

     // Display the contents of str via p. 
     for(int i=0; p[i] != 0; i++) 
       Console.Write(p[i]); 
   } 

   Console.WriteLine(); 
    
 } 

}


      </source>