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
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