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
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);
}
}
Address and size of pointer object
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();
}
}
Allocating Memory from the Stack
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]);
}
}
Fixing Managed Data in Memory
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]);
}
}
Get variable address in unsafe mode
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;
}
}
int pointer variable
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);
}
}
}
mark method as unsafe
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);
}
}
}
}
object pointer
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);
}
}
}
Supported sizeof() Types
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
unsafe and fixed block
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);
}
}
Unsafe code: get data type size
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);
}
}
Unsafe Methods
using System;
public class MyClass
{
public unsafe static void Main()
{
int MyInteger = 123;
int * MyIntegerPointer = &MyInteger;
Console.WriteLine(*MyIntegerPointer);
}
}
Use unsafe method to clone array
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);
}
}
}
Use unsage code to swap two integers
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);
}
}
Using the unsafe keyword
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 );
}
}