Csharp/C Sharp/Language Basics/Unsafe Code
Содержание
- 1 Accessing Structure Members with a Pointer
- 2 Address and size of pointer object
- 3 Allocating Memory from the Stack
- 4 Fixing Managed Data in Memory
- 5 Get variable address in unsafe mode
- 6 int pointer variable
- 7 mark method as unsafe
- 8 object pointer
- 9 Supported sizeof() Types
- 10 unsafe and fixed block
- 11 Unsafe code: get data type size
- 12 Unsafe Methods
- 13 Use unsafe method to clone array
- 14 Use unsage code to swap two integers
- 15 Using the unsafe keyword
Accessing Structure Members with a Pointer
<source lang="csharp"> using System;
public struct Point2D {
public int X; public int Y;
}
public class MyClass {
public unsafe static void Main() { Point2D MyPoint; Point2D * PointerToMyPoint; MyPoint = new Point2D(); PointerToMyPoint = &MyPoint; PointerToMyPoint->X = 100; PointerToMyPoint->Y = 200; Console.WriteLine("({0}, {1})", PointerToMyPoint->X, PointerToMyPoint->Y); }
}
</source>
Address and size of pointer object
<source lang="csharp"> using System; class MainEntryPoint {
static unsafe void Main() { int x = 10; short y = -1; byte y2 = 4; double z = 1.5; int* pX = &x; short* pY = &y; double* pZ = &z; Console.WriteLine("Address of x is 0x{0:X}, size is {1}, value is {2}",(uint)&x, sizeof(int), x); Console.WriteLine( "Address of y is 0x{0:X}, size is {1}, value is {2}", (uint)&y, sizeof(short), y); Console.WriteLine( "Address of y2 is 0x{0:X}, size is {1}, value is {2}", (uint)&y2, sizeof(byte), y2); Console.WriteLine( "Address of z is 0x{0:X}, size is {1}, value is {2}", (uint)&z, sizeof(double), z); Console.WriteLine( "Address of pX=&x is 0x{0:X}, size is {1}, value is 0x{2:X}", (uint)&pX, sizeof(int*), (uint)pX); Console.WriteLine( "Address of pY=&y is 0x{0:X}, size is {1}, value is 0x{2:X}", (uint)&pY, sizeof(short*), (uint)pY); Console.WriteLine( "Address of pZ=&z is 0x{0:X}, size is {1}, value is 0x{2:X}", (uint)&pZ, sizeof(double*), (uint)pZ); *pX = 20; Console.WriteLine("After setting *pX, x = {0}", x); Console.WriteLine("*pX = {0}", *pX); pZ = (double*)pX; Console.WriteLine("x treated as a double = {0}", *pZ); Console.ReadLine(); }
}
</source>
Allocating Memory from the Stack
<source lang="csharp"> using System;
public class MyClass {
public unsafe static void Main() { int * buf = stackalloc int [5]; for(int i = 0; i < 5; i++) buf[i] = i; for(int i = 0; i < 5; i++) Console.WriteLine(buf[i]); }
}
</source>
Fixing Managed Data in Memory
<source lang="csharp"> using System;
public class MyClass {
public unsafe static void Main() { int i; int [] intArr; intArr = new int [5]; fixed(int * IntegerPointer = intArr) { for(i = 0; i < 5; i++) IntegerPointer[i] = i; } for(i = 0; i < 5; i++) Console.WriteLine(intArr[i]); }
}
</source>
Get variable address in unsafe mode
<source lang="csharp"> using System; public class MainEntryPoint {
public static unsafe void Main() { Console.WriteLine("Size of Currency struct is " + sizeof(MyStruct)); MyStruct amount1, amount2; MyStruct* pointerStruct = &amount1; long* pDollars = &(pointerStruct->Dollars); byte* pCents = &(pointerStruct->Cents); Console.WriteLine("Address of amount1 is 0x{0:X}", (uint)&amount1); Console.WriteLine("Address of amount2 is 0x{0:X}", (uint)&amount2); Console.WriteLine("Address of pAmt is 0x{0:X}", (uint)&pointerStruct); Console.WriteLine("Address of pDollars is 0x{0:X}", (uint)&pDollars); Console.WriteLine("Address of pCents is 0x{0:X}", (uint)&pCents); pointerStruct->Dollars = 20; *pCents = 50; Console.WriteLine("amount1 contains " + amount1); --pointerStruct; Console.WriteLine("amount2 has address 0x{0:X} and contains {1}", (uint)pointerStruct, *pointerStruct); MyStruct* pTempCurrency = (MyStruct*)pCents; pCents = (byte*)(--pTempCurrency); Console.WriteLine("Address of pCents is now 0x{0:X}", (uint)&pCents); Console.WriteLine("\nNow with classes"); MyClass amount3 = new MyClass(); fixed (long* pDollars2 = &(amount3.Dollars)) fixed (byte* pCents2 = &(amount3.Cents)) { Console.WriteLine("amount3.Dollars has address 0x{0:X}", (uint)pDollars2); Console.WriteLine("amount3.Cents has address 0x{0:X}", (uint)pCents2); *pDollars2 = -100; Console.WriteLine("amount3 contains " + amount3); } }
} struct MyStruct {
public long Dollars; public byte Cents; public override string ToString() { return "$" + Dollars + "." + Cents; }
} class MyClass {
public long Dollars; public byte Cents; public override string ToString() { return "$" + Dollars + "." + Cents; }
}
</source>
int pointer variable
<source lang="csharp"> using System; public class MainClass {
static void Main(string[] args) { unsafe { int variable = 10; int* pVariable = &variable; Console.WriteLine("Value at address is {0}.", *pVariable); } }
}
</source>
mark method as unsafe
<source lang="csharp"> class FixedArrayApp {
unsafe public static void Foo(int* pa) { for (int* ip = pa; ip < (pa+5); ip++) { Console.Write("{0,-3}", *ip); } } static void Main(string[] args) { int[] ia = new int[5]{12,34,56,78,90}; unsafe { fixed (int* pa = ia) { Foo(pa); } } }
}
</source>
object pointer
<source lang="csharp"> using System; public struct MyValue {
public int id; private decimal price; public MyValue(int id, decimal price) { this.id = id; this.price = price; } public void Foo() { Console.WriteLine("Foo"); }
}
class DerefMemberApp {
static void Main(string[] args) { MyValue i = new MyValue(123, 45.67m); unsafe { MyValue* pi = &i; (*pi).Foo(); pi->Foo(); Console.WriteLine("id = {0}", pi->id); } }
}
</source>
Supported sizeof() Types
<source lang="csharp">
Expression Result sizeof(sbyte) 1 sizeof(byte) 1 sizeof(short) 2 sizeof(ushort) 2 sizeof(int) 4 sizeof(uint) 4 sizeof(long) 8 sizeof(ulong) 8 sizeof(char) 2 sizeof(float) 4 sizeof(double) 8 sizeof(bool) 1
</source>
unsafe and fixed block
<source lang="csharp"> public class MyValue {
public int id; public MyValue(int id) { this.id = id; }
}
class UnsafeClassApp {
unsafe public static void Swap(int* pi, int* pj) { int tmp = *pi; *pi = *pj; *pj = tmp; } static void Main(string[] args) { MyValue i = new MyValue(123); MyValue j = new MyValue(456); Console.WriteLine("Before Swap:\ti = {0}, j = {1}", i.id, j.id); unsafe { (int* pi = &i.id, pj = &j.id) { Swap(pi, pj); } } Console.WriteLine( "After Swap:\ti = {0}, j = {1}", i.id, j.id); }
}
</source>
Unsafe code: get data type size
<source lang="csharp">
using System; class MainEntryPoint { static unsafe void Main() { int x=100; short y = -19; byte y2 = 45; double z = 31.5; int *pX = &x; short *pY = &y; double *pZ = &z; Console.WriteLine("Address of x is 0x{0:X}, size is {1}, value is {2}", (uint)&x, sizeof(int), x); Console.WriteLine("Address of y is 0x{0:X}, size is {1}, value is {2}", (uint)&y, sizeof(short), y); Console.WriteLine("Address of y2 is 0x{0:X}, size is {1}, value is {2}",(uint)&y2, sizeof(byte), y2); Console.WriteLine("Address of z is 0x{0:X}, size is {1}, value is {2}", (uint)&z, sizeof(double), z); Console.WriteLine("Address of pX=&x is 0x{0:X}, size is {1}, value is 0x{2:X}",(uint)&pX, sizeof(int*), (uint)pX); Console.WriteLine("Address of pY=&y is 0x{0:X}, size is {1}, value is 0x{2:X}",(uint)&pY, sizeof(short*), (uint)pY); Console.WriteLine("Address of pZ=&z is 0x{0:X}, size is {1}, value is 0x{2:X}",(uint)&pZ, sizeof(double*), (uint)pZ); *pX = 20; Console.WriteLine("After setting *pX, x = {0}", x); Console.WriteLine("*pX = {0}", *pX); pZ = (double*)pX; Console.WriteLine("x treated as a double = {0}", *pZ); } }
</source>
Unsafe Methods
<source lang="csharp">
using System;
public class MyClass {
public unsafe static void Main() { int MyInteger = 123; int * MyIntegerPointer = &MyInteger; Console.WriteLine(*MyIntegerPointer); }
}
</source>
Use unsafe method to clone array
<source lang="csharp"> public struct MyValue {
public int id; public MyValue(int id) { this.id = id; }
} class ClassAddressApp {
unsafe public static MyValue[] CloneMyValues(MyValue[] box) { MyValue[] ret = new MyValue[box.Length]; fixed (MyValue* src = box, dest = ret) { MyValue* pSrc = src; MyValue* pDest = dest; for (int index = 0; index < box.Length; index++) { *pDest = *pSrc; pSrc++; pDest++; } } return ret; } static void Main(string[] args) { MyValue[] box = new MyValue[2]; box[0] = new MyValue(1); box[1] = new MyValue(2); MyValue[] bag = CloneMyValues(box); foreach (MyValue i in bag) { Console.WriteLine(i.id); } }
}
</source>
Use unsage code to swap two integers
<source lang="csharp">
public class TestUnsafeApp {
unsafe public static void Swap(int* pi, int* pj) { int tmp = *pi; *pi = *pj; *pj = tmp; } public static void Main(string[] args) { int i = 3; int j = 4; Console.WriteLine("BEFORE: i = {0}, j = {1}", i, j); unsafe { Swap(&i, &j); } Console.WriteLine("AFTER: i = {0}, j = {1}", i, j); }
}
</source>
Using the unsafe keyword
<source lang="csharp"> using System; class Test {
public static unsafe String UnsafeCodeExample( String s ) { int strLength = s.Length; char[] str = new char[strLength+1]; string strReturn = ""; fixed(char* strPointer = str) { for ( int i=0; i<strLength; ++i ) strReturn += strPointer[i]; } return strReturn; } public static void Main() { String s = UnsafeCodeExample("This is a test"); Console.WriteLine( "Reversed: {0}", s ); }
}
</source>