Csharp/CSharp Tutorial/unsafe/Pointer

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

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

using System; 
 
class MainClass{ 
  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."); 
    } 
  } 
}
p and p2 point to same address.

Assign value of myInt using pointer

using System;
using System.Globalization;

public class MainClass{
  public static void SomeUnsafeCode()
  {
    unsafe
    {
      int myInt;
      int* ptrToMyInt = &myInt;
      
      // Assign value of myInt using pointer.
      *ptrToMyInt = 123;  
      // print out address.
      Console.WriteLine("Value of myInt {0}", myInt);
      Console.WriteLine("Address of myInt {0:X}", (int)ptrToMyInt);
    }
  }
  static void Main(string[] args)
  {
        SomeUnsafeCode();
  }
}
Value of myInt 123
Address of myInt 12F474

C# Pointer Operators

Operator      Description
&             returns a pointer that represents the memory address of the variable.
*             to declare a variable to be a pointer of some type, 
              and to dereference the pointer value to get to the value of the variable pointed to by the pointer.
->            dereferencing and member access operator.

Declaring a Pointer

The general form of a pointer variable declaration is


type* var-name; 
int* ip;

Demonstrate the effects of pointer arithmethic

using System; 
 
class MainClass { 
  unsafe public static void Main() { 
    int i = 10;  
    double d = 10.0; 
 
    int* ip = &i; 
    double* fp = &d; 
 
    for(int x=0; x < 10; x++) { 
       Console.WriteLine((uint) (ip) + " " + 
                         (uint) (fp)); 
       ip++; 
       fp++; 
    } 
  } 
}
1242208 1242212
1242212 1242220
1242216 1242228
1242220 1242236
1242224 1242244
1242228 1242252
1242232 1242260
1242236 1242268
1242240 1242276
1242244 1242284

Get a pointer to the start of a string and display the contents of string via pointer

using System; 
 
class MainClass { 
  unsafe public static void Main() { 
    string str = "this is a test"; 
 
    fixed(char* p = str) { 
      for(int i=0; p[i] != 0; i++) 
        Console.Write(p[i]); 
    } 
    Console.WriteLine(); 
  } 
}
this is a test

Index pointer

using System; 
 
class MainClass { 
  unsafe public static void Main() { 
    int[] nums = new int[10]; 
 
    
    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]); 
    } 
 
  } 
}
Index pointer like array.
p[0]: 0
p[1]: 1
p[2]: 2
p[3]: 3
p[4]: 4
p[5]: 5
p[6]: 6
p[7]: 7
p[8]: 8
p[9]: 9

IntPtrs and unsafe bit-twiddling

Pointers are variables that hold the addresses of other variables.


using System;
using System.IO;
using System.Reflection;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
public class MainClass
{
    public unsafe static void Main()
    {
        int a = 10;
        Console.WriteLine("a is {0} ({0:X})", a);
        IntPtr ip = new IntPtr(&a);
        byte* pTarget = (byte*)ip.ToPointer() + 1;
        *pTarget = 2;
        Console.WriteLine("a is {0} ({0:X})", a);
    }
}
a is 10 (A)
a is 522 (20A)

Modifying an Immutable String with Pointer

class MainClass
{
  static void Main()
  {
    string text = "S5280ft";
    System.Console.Write("{0} = ", text);
    unsafe{
    fixed (char* pText = text)
      {
          char* p = pText;
          *++p = "m";
          *++p = "i";
          *++p = "l";
          *++p = "e";
          *++p = "A";
          *++p = "B";
      }
    }
    System.Console.WriteLine(text);
    
  }
}

Pointer arithmetic

using System; 
 
class MainClass { 
  unsafe public static void Main() { 
    int[] nums = new int[10]; 
 
    Console.WriteLine("\nUse pointer arithmetic."); 
    fixed (int* p = nums) { 
      for(int i=0; i < 10; i++)  
        *(p+i) = i;
 
      for(int i=0; i < 10; i++)  
        Console.WriteLine("*(p+{0}): {1} ", i, *(p+i)); 
    } 
  } 
}
Use pointer arithmetic.
*(p+0): 0
*(p+1): 1
*(p+2): 2
*(p+3): 3
*(p+4): 4
*(p+5): 5
*(p+6): 6
*(p+7): 7
*(p+8): 8
*(p+9): 9

Pointer of a pointer

using System; 
 
class MainClass { 
  unsafe public static void Main() { 
    int x;    // an int value  
    int* p;   // an int pointer 
    int** q;  // an pointer to an int pointer 
 
    x = 10; 
    p = &x; 
    q = &p; 
 
    Console.WriteLine(**q); 
  } 
}
10

Safe Swap

using System;
using System.Globalization;
public class MainClass{
  public static void SafeSwap(ref int i, ref int j)
  {
    int temp = i;
    i = j;
    j = temp;
  }
  static void Main(string[] args)
  {
    int i = 10, j = 20;
    
    Console.WriteLine("Values before safe swap: i = {0}, j = {1}", i, j);
    SafeSwap(ref i, ref j);
    Console.WriteLine("Values after safe swap: i = {0}, j = {1}", i, j);
  }
}
Values before safe swap: i = 10, j = 20
Values after safe swap: i = 20, j = 10

The & is a unary operator that returns the memory address of its operand

using System;
class MainClass
{
  static unsafe void print( char* p, int len )
  {
    for ( int i = 0; i < len; i++, p++ )
    {
      Console.WriteLine( *p );
    }
  }
  [STAThread]
  static unsafe void Main(string[] args)
  {
    string s = "unsafe code";
    fixed ( char* p = &( s.ToCharArray()[ 0 ] ) )
    {
      print ( p, s.Length );
    }
  }
}
u
n
s
a
f
e
c
o
d
e

Unsafe swap

using System;
using System.Globalization;
public class MainClass{
  unsafe public static void UnsafeSwap(int* i, int* j)
  {
    int temp = *i;
    *i = *j;
    *j = temp;
  }

  static void Main(string[] args)
  {
    int i = 10, j = 20;
    
    Console.WriteLine("Unsafe swap");
    Console.WriteLine("Values before unsafe swap: i = {0}, j = {1}", i, j);
    unsafe{ UnsafeSwap(&i, &j);} 
    Console.WriteLine("Values after unsafe swap: i = {0}, j = {1}", i, j);
  }
}
Unsafe swap
Values before unsafe swap: i = 10, j = 20
Values after unsafe swap: i = 20, j = 10

Use fixed to put address of value into a pointer

using System; 
 
class MyClass { 
  public int num; 
  public MyClass(int i) { num = i; } 
} 
 
class FixedCode { 
  unsafe public static void Main() { 
    MyClass o = new MyClass(19); 
 
    fixed (int* p = &o.num) {  
 
      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); 
    } 
  } 
}
Initial value of o.num is 19
New value of o.num is 10