Csharp/CSharp Tutorial/unsafe/Pointer

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

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

<source lang="csharp">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."); 
   } 
 } 

}</source>

p and p2 point to same address.

Assign value of myInt using pointer

<source lang="csharp">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();
 }

}</source>

Value of myInt 123
Address of myInt 12F474

C# Pointer Operators

<source lang="csharp">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.</source>

Declaring a Pointer

The general form of a pointer variable declaration is


<source lang="csharp">type* var-name; int* ip;</source>

Demonstrate the effects of pointer arithmethic

<source lang="csharp">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++; 
   } 
 } 

}</source>

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

<source lang="csharp">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(); 
 } 

}</source>

this is a test

Index pointer

<source lang="csharp">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]); 
   } 

 } 

}</source>

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.


<source lang="csharp">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);
   }

}</source>

a is 10 (A)
a is 522 (20A)

Modifying an Immutable String with Pointer

<source lang="csharp">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);
   
 }

}</source>

Pointer arithmetic

<source lang="csharp">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)); 
   } 
 } 

}</source>

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

<source lang="csharp">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); 
 } 

}</source>

10

Safe Swap

<source lang="csharp">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);
 }

}</source>

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

<source lang="csharp">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 );
   }
 }

}</source>

u
n
s
a
f
e
c
o
d
e

Unsafe swap

<source lang="csharp">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);
 }

}</source>

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

<source lang="csharp">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); 
   } 
 } 

}</source>

Initial value of o.num is 19
New value of o.num is 10