C#中慎用指针
1.指针运算:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace PointerPlaygroubnd { class Program { //使用指针是不安全的使用unsafe关键字 static unsafe void Main(string[] args) { int x = 10; short y = -1; byte b = 4; double z = 1.5; int* pX = &x; //指针指向x的地址 short* pY = &y; //指针指向y的地址 double* pZ = &z; //指针指向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 b is 0x{0:X},size is {1},value is {2}",(uint)&b,sizeof(byte),b); 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 is 0x{0:X},size is {1},value is {2}",(uint)&pX,sizeof(int*),(uint)*pX); Console.WriteLine("Address of pY is 0x{0:X},size is {1},value is {2}",(uint)&pY,sizeof(short*),(uint)*pY); Console.WriteLine("Address of pZ is 0x{0:X},size is {1},value is {2}",(uint)&pZ,sizeof(double*),(uint)*pZ); *pX = 20; //更改只指针的值相当于改变指针指向地址的值,x的值对应发生变化 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.WriteLine(); } } }
运行结果:
2.指针操作类和结构体
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace PointerPlayground2 { class Program { //结构体 internal struct CurrentcyStruct { public long Dollars; public byte Cents; public override string ToString() { return "$" + Dollars + "." + Cents; } } //类 internal class CurrentcyClass { public long Dollars; public byte Cents; public override string ToString() { return "$" + Dollars + "." + Cents; } } static unsafe void Main(string[] args) { Console.WriteLine("Size of CurrentcyStruct struct is " + sizeof(CurrentcyStruct)); CurrentcyStruct amount1, amount2; CurrentcyStruct* pAmount = &amount1; long* pDollars = &(pAmount->Dollars); byte* pCents = &(pAmount->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 pAmount is 0x{0:X}", (uint)&pAmount); Console.WriteLine("Address of pDollars is 0x{0:X}", (uint)&pDollars); Console.WriteLine("Address of pCents is 0x{0:X}", (uint)&pCents); pAmount->Dollars = 20; *pCents = 50; Console.WriteLine("amount1 contains "+ amount1); //类的指针操作 //fixed 语句禁止垃圾回收器重定位可移动的变量。 fixed 语句只在不安全的上下文中是允许的。 Fixed 还可用于创建固定大小缓冲区 //fixed 语句设置指向托管变量的指针,并在执行该语句期间“固定”此变量。 如果没有 fixed 语句,则指向可移动托管变量的指针的作用很小, //因为垃圾回收可能不可预知地重定位变量。 C# 编译器只允许在 fixed 语句中分配指向托管变量的指针。 Console.WriteLine("==========Class=========="); unsafe { CurrentcyClass amount3 = new CurrentcyClass(); fixed (long* pDollar3 = &(amount3.Dollars)) { fixed (byte* pCents3 = &(amount3.Cents)) { Console.WriteLine("Address of amount3.Dollars is 0x{0:X}", (uint)pDollar3); Console.WriteLine("Address os amount3.Cents is 0x{0:X}", (uint)pCents3); *pDollar3 = -100; Console.WriteLine("amount3 contains " + amount3); } } } } } }
运行结果
3.指针优化数组
using System; using System.Collections.Generic; using System.Linq; using System.Text; //利用指针创建基于栈的数组,减少堆的内存开销 namespace QuickArray { class Program { static unsafe void Main(string[] args) { //输入数组长度 Console.Write("How big an array do you want? "); string userInput = Console.ReadLine(); uint size = uint.Parse(userInput); //创建基于栈的数组,长度为输入的长度 long* pArray = stackalloc long[(int)size]; //初始化数组 for (int i = 0; i < size; i++) { pArray[i] = i * i; } //遍历数组 for (int i = 0; i < size; i++) { //Console.WriteLine("Element {0}={1}",i,*(pArray+i)); //第一种方式 Console.WriteLine("Element {0}={1}", i, pArray[i]); //第二种方式 } Console.WriteLine(); } } }
运行结果: