Csharp/CSharp Tutorial/unsafe/Pointer
Содержание
- 1 An array name with an index yields a pointer to the start of the array
- 2 Assign value of myInt using pointer
- 3 C# Pointer Operators
- 4 Declaring a Pointer
- 5 Demonstrate the effects of pointer arithmethic
- 6 Get a pointer to the start of a string and display the contents of string via pointer
- 7 Index pointer
- 8 IntPtrs and unsafe bit-twiddling
- 9 Modifying an Immutable String with Pointer
- 10 Pointer arithmetic
- 11 Pointer of a pointer
- 12 Safe Swap
- 13 The & is a unary operator that returns the memory address of its operand
- 14 Unsafe swap
- 15 Use fixed to put address of value into a pointer
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