C#为了类型安全,默认并不支持指针。但是也并不是说C#不支持指针,我们可以使用unsafe关键词,开启不安全代码(unsafe code)开发模式。在不安全模式下,我们可以直接操作内存,这样就可以使用指针了。在不安全模式下,CLR并不检测unsafe代码的安全,而是直接执行代码。unsafe代码的安全需要开发人员自行检测。

一、Vs2010中开启unsafe code 的方式

在方法、类、代码块中使用unsafe关键词,如:
unsafe static void Main(string[] args){ //代码}

unsafe
{
//代码块
}
然后再项目上点击鼠标右键,选择“属性”,在“生成”选项卡中选中“允许不安全代码”

二、C#可以定义为指针的类型有

sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool,
struct(结构体),结构体中只能包括非托管类型。

三、C#指针操作符

操作符 说明
* 取值运算符

& 取址运算符
-> 通过指针处理结构体中的数据(获取或赋值)
++与– 指针增、减操作
fixed 用户暂时固定托管代码中引用类型的位置。
Stackallc 分配内存

例如分配内存

char* cptr = stackalloc char[26]; for (int i = 0; i < 26;i++ ) { cptr[i] = (char) (i+65); } for (int i = 0; i < 26;i++ ) { Console.WriteLine(string.Format("{0}:{1}",(int)&cptr[i],cptr[i])); }

至于释放内存,我在msdn上搜索了一下,c#并没有提供释放内存的函数。而msdn给的解释是:分配的内存会在方法结束后自动释放。
fixed的应用会在下面的类与指针中做说明。

四、C#指针的定义

定义指针 说明
int* p 整形指针
int** p 指向整形指针的指针
char* c 指向字符的指针
int*[] arr 整形一维数组指针

五、指针的使用

1.整形指针的使用

int i=10; int* iptr = &i; //将i的地址赋值给iptr Console.WriteLine((int)&iptr); //取iptr得地址 Console.WriteLine(*iptr); //取iptr指向的值

2.结构体指针

struct Location { public int X; public int Y; } unsafe static void Main(string[] args) { Location location; location.X = 10; location.Y = 5; Location* lptr = &location; Console.WriteLine(string.Format("location 地址{0},lptr地址{1},lptr值{2}",(int)&location,(int)lptr,*lptr)); Console.WriteLine(string.Format("location.x的地址{0},location.x的值{1}",(int)&(lptr->X),lptr->X)); Console.WriteLine(string.Format("location.y的地址{0},location.y的值{1}", (int)&(lptr->Y), lptr->Y)); }

以上代码输出结构体的地址和值。我们在操作地址时,可以直接看到结构体的内存分配。

3.指针与参数

public static unsafe int* Add(int* x,int* y) { int sum = *x + *y; return &sum; } int i = 2, j = 3; Console.WriteLine(*Add(&i,&j));

4.类与指针,因为类是托管类型,我们知道类受到“垃圾收集”的影响,它的内存地址是不固定的。而且类是引用类型,是不能声明为指针类型的。而指针分配内存后,不受“垃圾收集”影响,地址是固定的。所以为了使用类中的数据,我们需要临时固定类的地址。这就用到fixed关键词,用fixed后,就可以操作类中的值类型了。

class People { public int Age; //值类型,不可以是属性 public void ShowAge() { Console.WriteLine(Age); } } People people = new People(); people.Age = 10; fixed(int* agePtr=&people.Age) { *agePtr += 1; } people.ShowAge(); //11

通过以上的方法,我们可以操作值类型,也可以获得值类型的地址。但如何获取类的内存地址?我们可以使用GCHandle,来自System.Runtime.InteropServices命名空间。GCHandle提供从非托管内存访问托管对象的方法。如下:

object p = new People(); GCHandle h = GCHandle.Alloc(p, GCHandleType.Pinned); IntPtr addr = h.AddrOfPinnedObject(); Console.WriteLine(addr.ToString()); h.Free();

六、C#中使用指针的总结

1.引用类型不能定义为指针
2.msdn上说enum可以定义为指针,可是我真不知道它的用处是什么。所以在指针的类型中并没有出现enum类型。
3.c#中的指针操作远远不如c/c++,如果想学习指针的话,还是用c/c++
4.微软并不推荐使用unsafe code模式,也不推荐使用指针。在msdn官方文档中,唯一一句赞美C#指针的话就是“合理的使用指针,可以提高程序的执行速度”。但是什么是“合理的使用”?我下载了msdn上的几个关于C#指针的实例代码,发现用的最多的是调用api函数,在api函数中,有大量的指针参数。
5.fixed的使用可能产生存储碎片,因为它们不能移动。如果确实需要固定对象,固定对象的时间应该越短越好。
6.可以使我们了解非托管类型的内存分配。

C#中指针使用总结的更多相关文章

  1. Objective-C 和 C++中指针的格式和.方法 和内存分配

    最近在看cocos2d-x,于是打算复习一下C++,在这里简单对比下,留个念想. 先看看oc中指针的用法 @interface ViewController : UIViewController { ...

  2. 上机实践 - - 一个例子了解C/C++中指针与数组的区别

    本例子来自于<剑指Offer>(P37) 解答如下: size1:20 data1是一个数组,sizeof(data1)是求数组大小. 这个数组包含5个整数,每个整数4个字节,共20字节. ...

  3. (原)C++中指针不初始化就传递的问题

    C++中指针的使用.以前在使用指针之前都会初始化.今天没有初始化,然后指针传递后没有内容(testptrnoret),后来发现返回指针的话(testptrret),就可以了. // testptr.c ...

  4. Keil C51 中指针的使用

    指针是C语言中比较难的一个内容,Keil C51在指针方面有和标准C不一样的地方,今天看了一些资料学习了一下Keil C51 中指针的使用. keil51的指针,包含两种指针:普通指针,兼容标准C:内 ...

  5. C语言中指针*p[N], (*P)[N],及**p的区别

    在C语言编程中指针经常困扰着我们,但是若能灵活运用指针的话,将会使得我们编程变得更加轻松与高效.这里讲下*p[N], (*P)[N],及**p的区别,这也是之前经常困扰我的地方. 这三者的定义分别为: ...

  6. C中指针符*和取址符&

    学习了C语言之后,关于指针部分看了无数遍,有时候明明觉得自己看懂了,指针就是地址,但是总是在看代码时候糊里糊涂的搞不明白,最近又关于指针强化了一把. 大部分情况下对于程序中指针糊涂是因为不明白指针符“ ...

  7. C语言中指针占据内存空间问题

    以前一直有个疑问,指向不同类型的指针到底占用的内存空间是多大呢? 这个问题我多次问过老师,老师的答案是"指向不同类型的指针占据的内存空间大小不同",我一直很之一这个答案,今天我就做 ...

  8. 转 浅谈C++中指针和引用的区别

    浅谈C++中指针和引用的区别 浅谈C++中指针和引用的区别   指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法. 1.指针和引用的定义和性 ...

  9. 理解C语言中指针的声明以及复杂声明的语法

    昨天刚把<C程序设计语言>中"指针与数组"章节读完,最终把心中的疑惑彻底解开了.如今记录下我对指针声明的理解.顺便说下怎样在C语言中创建复杂声明以及读懂复杂声明. 本文 ...

  10. 这样子来理解C语言中指针的指针

    友情提示:阅读本文前,请先参考我的之前的文章<从四个属性的角度来理解C语言的指针也许会更好理解>,若已阅读,请继续往下看. 我从4个属性的角度来总结了C语言中的指针概念.对于C语言的一个指 ...

随机推荐

  1. Extended ComboBox添加图标

    Extended ComboBox添加图标 关键点 实现过程 // MFC02Dlg.h : header fileCImageList m_imageList;  // MFC02Dlg.cpp : ...

  2. JS数组定义

     JS数组定义收藏 function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.create ...

  3. direct3D directX

    direct3D只是directX其中一个增强功能 DirectX是由很多API组成的,按照性质分类,可以分为四大部分,显示部分.声音部分.输入部分和网络部分. 显示部分担任图形处理的关键,分为Dir ...

  4. find——文件查找命令 linux一些常用命令

    find 命令eg: 一般文件查找方法: 1.  find /home -name file  ,  在/home目录下查找文件名为file的文件2.  find /home -name '*file ...

  5. 初识hibernate

    //针对myEclipse2014版本 怎样新建一个工程实现这些东西的导入. 打开myeclipse. 2.点击右上角的open perspective 找到这个 MyEclipse Database ...

  6. Java 计算文件大小

    long available = (long)getAttachmentContent(att.getId()).available();   public static String bytesTr ...

  7. Magento强大的配置系统

    Magento的配置系统就像是Magento的心脏,支撑着Magento的运行.这套配置系统掌管着几乎所有"module/model/class/template/etc".它把整 ...

  8. 使用canvas制作在线画板

    canvas绘图的强大功能,让人前仆后继的去研究它.代码全部加起来不足百行.还用到了h5中的<input type="color"/>和<input type=& ...

  9. wap上传图片跨域发送post请求

    wap和接口交互是跨域请求,一般只能通过Jsonp来进行数据的吞吐,然而jsonp只是GET请求,不能发送post请求,所以会对项目需求有所限制. 需求:wap跨域通过接口上传图片. 条件:接口是C# ...

  10. Android TabHost的使用

    标签显示界面的主要特点是可以在一个窗口中显示多组标签栏的类容. 在Android系统中,每个标签栏称为一个Tab,而包含多个标签栏的内容就称为TabHost. 通过TabHost的继承结构来看,Tab ...