Csharp/C Sharp/Language Basics/Pointer Unsafe
Содержание
- 1 An array name with an index yields a pointer to the start of the array
- 2 Demonstrate fixed
- 3 Demonstrate pointer comparison
- 4 Demonstrate pointers and unsafe
- 5 Demonstrate the effects of pointer arithmethic
- 6 Index a pointer as if it were an array
- 7 Multiple Indirect
- 8 Pointers and Declarative Pinning
- 9 References and Pointers
- 10 Unsafe code: copy
- 11 Unsafe Context
- 12 Use fixed to get a pointer to the start of a string
An array name with an index yields a pointer to the start of the array
/*
C#: The Complete Reference
by Herbert Schildt
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/
/* An array name with an index yields a pointer to the
start of the array. */
using System;
public class PtrArray {
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.");
}
}
}
Demonstrate fixed
/*
C#: The Complete Reference
by Herbert Schildt
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/
// Demonstrate fixed.
using System;
class Test {
public int num;
public Test(int i) { num = i; }
}
public class FixedCode {
// mark Main as unsafe
unsafe public static void Main() {
Test o = new Test(19);
fixed (int* p = &o.num) { // use fixed to put address of o.num into p
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);
}
}
}
Demonstrate pointer comparison
/*
C#: The Complete Reference
by Herbert Schildt
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/
// Demonstrate pointer comparison.
using System;
public class PtrCompDemo {
unsafe public static void Main() {
int[] nums = new int[11];
int x;
// find the middle
fixed (int* start = &nums[0]) {
fixed(int* end = &nums[nums.Length-1]) {
for(x=0; start+x <= end-x; x++) ;
}
}
Console.WriteLine("Middle element is " + x);
}
}
Demonstrate pointers and unsafe
/*
C#: The Complete Reference
by Herbert Schildt
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/
// Demonstrate pointers and unsafe.
using System;
public class UnsafeCode {
// mark Main as unsafe
unsafe public static void Main() {
int count = 99;
int* p; // create an int pointer
p = &count; // put address of count into p
Console.WriteLine("Initial value of count is " + *p);
*p = 10; // assign the to count via p
Console.WriteLine("New value of count is " + *p);
}
}
Demonstrate the effects of pointer arithmethic
/*
C#: The Complete Reference
by Herbert Schildt
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/
// Demonstrate the effects of pointer arithmethic.
using System;
public class PtrArithDemo {
unsafe public static void Main() {
int x;
int i;
double d;
int* ip = &i;
double* fp = &d;
Console.WriteLine("int double\n");
for(x=0; x < 10; x++) {
Console.WriteLine((uint) (ip) + " " +
(uint) (fp));
ip++;
fp++;
}
}
}
Index a pointer as if it were an array
/*
C#: The Complete Reference
by Herbert Schildt
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/
// Index a pointer as if it were an array.
using System;
public class PtrIndexDemo {
unsafe public static void Main() {
int[] nums = new int[10];
// index pointer
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]);
}
// use pointer arithmetic
Console.WriteLine("\nUse pointer arithmetic.");
fixed (int* p = nums) {
for(int i=0; i < 10; i++)
*(p+i) = i; // use pointer arithmetic
for(int i=0; i < 10; i++)
Console.WriteLine("*(p+{0}): {1} ", i, *(p+i));
}
}
}
Multiple Indirect
/*
C#: The Complete Reference
by Herbert Schildt
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/
using System;
public class MultipleIndirect {
unsafe public static void Main() {
int x; // holds a int value
int* p; // holds an int pointer
int** q; // holds an pointer to an int pointer
x = 10;
p = &x; // put address of x into p
q = &p; // put address of p into q
Console.WriteLine(**q); // display the value of x
}
}
Pointers and Declarative Pinning
/*
A Programmer"s Introduction to C# (Second Edition)
by Eric Gunnerson
Publisher: Apress L.P.
ISBN: 1-893115-62-3
*/
// 31 - Interop\Calling Native DLL Functions\Pointers and Declarative Pinning
// copyright 2000 Eric Gunnerson
// file=ReadFileUnsafe.cs
// compile with: csc /unsafe ReadFileUnsafe.cs
using System;
using System.Runtime.InteropServices;
using System.Text;
class FileRead
{
const uint GENERIC_READ = 0x80000000;
const uint OPEN_EXISTING = 3;
int handle;
public FileRead(string filename)
{
// opens the existing file
handle = CreateFile( filename,
GENERIC_READ,
0,
0,
OPEN_EXISTING,
0,
0);
}
[DllImport("kernel32", SetLastError=true)]
static extern int CreateFile(
string filename,
uint desiredAccess,
uint shareMode,
uint attributes, // really SecurityAttributes pointer
uint creationDisposition,
uint flagsAndAttributes,
uint templateFile);
[DllImport("kernel32", SetLastError=true)]
static extern unsafe bool ReadFile(
int hFile,
void* lpBuffer,
int nBytesToRead,
int* nBytesRead,
int overlapped);
public unsafe int Read(byte[] buffer, int count)
{
int n = 0;
fixed (byte* p = buffer)
{
ReadFile(handle, p, count, &n, 0);
}
return n;
}
}
public class PointersandDeclarativePinning
{
public static void Main(string[] args)
{
FileRead fr = new FileRead(args[0]);
byte[] buffer = new byte[128];
ASCIIEncoding e = new ASCIIEncoding();
// loop through, read until done
Console.WriteLine("Contents");
while (fr.Read(buffer, 128) != 0)
{
Console.Write("{0}", e.GetString(buffer));
}
}
}
References and Pointers
/*
* C# Programmers Pocket Consultant
* Author: Gregory S. MacBeth
* Email: gmacbeth@comporium.net
* Create Date: June 27, 2003
* Last Modified Date:
*/
using System;
using System.Runtime.InteropServices;
namespace Client.Chapter_7___References__Pointers_and_Memory_Management
{
public class ReferencesandPointers
{
static void Main(string[] args)
{
UsePointers();
}
static unsafe public void UsePointers()
{
char * pMyArray = (char*)Marshal.AllocCoTaskMem(6);
while (*pMyArray != "\0")
{
Console.WriteLine(*pMyArray);
pMyArray++;
}
Marshal.FreeCoTaskMem((IntPtr)pMyArray);
}
}
}
Unsafe code: copy
/*
C# Programming Tips & Techniques
by Charles Wright, Kris Jamsa
Publisher: Osborne/McGraw-Hill (December 28, 2001)
ISBN: 0072193794
*/
namespace nsType
{
using System;
public class IntCopy
{
public static void Main ()
{
int [] arr1 = new int[] {1, 4, 2, 8, 5, 7};
int [] arr2 = new int[arr1.Length];
MemCpy (arr2, arr1, arr1.Length);
arr1[0] = 142857;
for (int x = 0; x < arr1.Length; ++x)
{
Console.Write ("arr1[{0}] = {1}\t", x, arr1[x]);
Console.Write ("arr2[{0}] = {1}\n", x, arr2[x]);
}
}
static unsafe public void MemCpy (int [] dst, int [] src, int size)
{
if ((size > dst.Length) || (size > src.Length))
{
ArgumentException e = new ArgumentException("The size argument is too large for one of the array arguments");
throw (e);
}
fixed (int *Src = src, Dst = dst)
{
int* pSrc = Src;
int* pDst = Dst;
for (int n = 0; n < size; ++n)
{
*pDst++ = *pSrc++;
}
}
}
}
}
Unsafe Context
/*
A Programmer"s Introduction to C# (Second Edition)
by Eric Gunnerson
Publisher: Apress L.P.
ISBN: 1-893115-62-3
*/
// 36 - Deeper into C#\Unsafe Context
// copyright 2000 Eric Gunnerson
// file=unsafe.cs
// compile with: csc /unsafe /o+ unsafe.cs
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public class UnsafeContext
{
const int iterations = 20000; // # to do copy
const int points = 1000; // # of points in array
const int retryCount = 5; // # of times to retry
public delegate Point[] CloneFunction(Point[] a);
public static void TimeFunction(Point[] arr,
CloneFunction func, string label)
{
Point[] arrCopy = null;
long start;
long delta;
double min = 5000.0d; // big number;
// do the whole copy retryCount times, find fastest time
for (int retry = 0; retry < retryCount; retry++)
{
start = Counter.Value;
for (int iterate = 0; iterate < iterations; iterate++)
arrCopy = func(arr);
delta = Counter.Value - start;
double result = (double) delta / Counter.Frequency;
if (result < min)
min = result;
}
Console.WriteLine("{0}: {1:F3} seconds", label, min);
}
public static void Main()
{
Console.WriteLine("Points, Iterations: {0} {1}", points, iterations);
Point[] arr = new Point[points];
for (int index = 0; index < points; index++)
arr[index] = new Point(3, 5);
TimeFunction(arr,
new CloneFunction(Point.ClonePointArrayMemcpy), "Memcpy");
TimeFunction(arr,
new CloneFunction(Point.ClonePointArrayUnsafe), "Unsafe");
TimeFunction(arr,
new CloneFunction(Point.ClonePointArray), "Baseline");
}
}
class Counter
{
public static long Frequency
{
get
{
long freq = 0;
QueryPerformanceFrequency(ref freq);
return freq;
}
}
public static long Value
{
get
{
long count = 0;
QueryPerformanceCounter(ref count);
return count;
}
}
[System.Runtime.InteropServices.DllImport("KERNEL32",
CharSet=System.Runtime.InteropServices.CharSet.Auto)]
private static extern bool QueryPerformanceCounter( ref long lpPerformanceCount);
[System.Runtime.InteropServices.DllImport("KERNEL32",
CharSet=System.Runtime.InteropServices.CharSet.Auto)]
private static extern bool QueryPerformanceFrequency( ref long lpFrequency);
}
public struct Point
{
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// safe version
public static Point[] ClonePointArray(Point[] a)
{
Point[] ret = new Point[a.Length];
for (int index = 0; index < a.Length; index++)
ret[index] = a[index];
return(ret);
}
// unsafe version using pointer arithmetic
unsafe public static Point[] ClonePointArrayUnsafe(Point[] a)
{
Point[] ret = new Point[a.Length];
// a and ret are pinned; they cannot be moved by
// the garbage collector inside the fixed block.
fixed (Point* src = a, dest = ret)
{
Point* pSrc = src;
Point* pDest = dest;
for (int index = 0; index < a.Length; index++)
{
*pDest = *pSrc;
pSrc++;
pDest++;
}
}
return(ret);
}
// import CopyMemory from kernel32
[DllImport("kernel32.dll")]
unsafe public static extern void
CopyMemory(void* dest, void* src, int length);
// unsafe version calling CopyMemory()
unsafe public static Point[] ClonePointArrayMemcpy(Point[] a)
{
Point[] ret = new Point[a.Length];
fixed (Point* src = a, dest = ret)
{
CopyMemory(dest, src, a.Length * sizeof(Point));
}
return(ret);
}
public override string ToString()
{
return(String.Format("({0}, {1})", x, y));
}
int x;
int y;
}
Use fixed to get a pointer to the start of a string
/*
C#: The Complete Reference
by Herbert Schildt
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/
// Use fixed to get a pointer to the start of a string.
using System;
public class FixedString {
unsafe public static void Main() {
string str = "this is a test";
// Point p to start of str.
fixed(char* p = str) {
// Display the contents of str via p.
for(int i=0; p[i] != 0; i++)
Console.Write(p[i]);
}
Console.WriteLine();
}
}