Csharp/C Sharp/Language Basics/Pointer Unsafe

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

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

/*
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."); 
    } 
  } 
}


Demonstrate fixed

/*
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); 
    } 
  } 
}


Demonstrate pointer comparison

/*
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); 
  } 
}


Demonstrate pointers and unsafe

/*
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); 
  } 
}


Demonstrate the effects of pointer arithmethic

/*
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++; 
    } 
  } 
}


Index a pointer as if it were an array

/*
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)); 
    } 
  } 
}


Multiple Indirect

/*
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  
  } 
}


Pointers and Declarative Pinning

/*
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));
        }
    }
}


References and Pointers

/*
 * 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);
    }
  }
}


Unsafe code: copy

/*
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++;
                }
            }
        }
    }
}


Unsafe Context

/*
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;
}


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

/*
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(); 
     
  } 
}