C#中指针使用总结(转载)
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[];
- for (int i = ; i < ;i++ )
- {
- cptr[i] = (char) (i+);
- }
- for (int i = ; i < ;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=;
- 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 = ;
- location.Y = ;
- 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 ∑
- }
- int i = , j = ;
- 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 = ;
- fixed(int* agePtr=&people.Age)
- {
- *agePtr += ;
- }
- people.ShowAge(); //
通过以上的方法,我们可以操作值类型,也可以获得值类型的地址。但如何获取类的内存地址?我们可以使用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#中指针使用总结(转载)的更多相关文章
- C语言中指针和数组
C语言数组与指针的那些事儿 在C语言中,要说到哪一部分最难搞,首当其冲就是指针,指针永远是个让人又爱又恨的东西,用好了可以事半功倍,用不好,就会有改不完的bug和通不完的宵.但是程序员一般都有一种迷之 ...
- Objective-C 和 C++中指针的格式和.方法 和内存分配
最近在看cocos2d-x,于是打算复习一下C++,在这里简单对比下,留个念想. 先看看oc中指针的用法 @interface ViewController : UIViewController { ...
- c语言指针详解(转载)
转自(http://blog.csdn.net/ad_ad_ad/article/details/1522145) 指针是C语言中广泛使用的一种数据类型. 运用指针编程是C语言最主要的风格之一.利用指 ...
- spring中context:property-placeholder/元素 转载
spring中context:property-placeholder/元素 转载 1.有些参数在某些阶段中是常量 比如 :a.在开发阶段我们连接数据库时的连接url,username,passwo ...
- 上机实践 - - 一个例子了解C/C++中指针与数组的区别
本例子来自于<剑指Offer>(P37) 解答如下: size1:20 data1是一个数组,sizeof(data1)是求数组大小. 这个数组包含5个整数,每个整数4个字节,共20字节. ...
- (原)C++中指针不初始化就传递的问题
C++中指针的使用.以前在使用指针之前都会初始化.今天没有初始化,然后指针传递后没有内容(testptrnoret),后来发现返回指针的话(testptrret),就可以了. // testptr.c ...
- Keil C51 中指针的使用
指针是C语言中比较难的一个内容,Keil C51在指针方面有和标准C不一样的地方,今天看了一些资料学习了一下Keil C51 中指针的使用. keil51的指针,包含两种指针:普通指针,兼容标准C:内 ...
- C语言中指针*p[N], (*P)[N],及**p的区别
在C语言编程中指针经常困扰着我们,但是若能灵活运用指针的话,将会使得我们编程变得更加轻松与高效.这里讲下*p[N], (*P)[N],及**p的区别,这也是之前经常困扰我的地方. 这三者的定义分别为: ...
- C中指针符*和取址符&
学习了C语言之后,关于指针部分看了无数遍,有时候明明觉得自己看懂了,指针就是地址,但是总是在看代码时候糊里糊涂的搞不明白,最近又关于指针强化了一把. 大部分情况下对于程序中指针糊涂是因为不明白指针符“ ...
- C语言中指针占据内存空间问题
以前一直有个疑问,指向不同类型的指针到底占用的内存空间是多大呢? 这个问题我多次问过老师,老师的答案是"指向不同类型的指针占据的内存空间大小不同",我一直很之一这个答案,今天我就做 ...
随机推荐
- Java开发知识之Java的枚举
Java开发知识之Java的枚举 一丶什么是枚举 枚举可以理解为就是常量,在Java中我们定义常量.都是用 final语句. C++中都是用const关键字. 枚举跟C++概念都是一样的.就是特定的常 ...
- ES6躬行记(13)——类型化数组
类型化数组(Typed Array)是一种处理二进制数据的特殊数组,它可像C语言那样直接操纵字节,不过得先用ArrayBuffer对象创建数组缓冲区(Array Buffer),再映射到指定格式的视图 ...
- 阿里云弹性容器实例产品 ECI ——云原生时代的基础设施
阿里云弹性容器实例产品 ECI ——云原生时代的基础设施 1. 什么是 ECI 弹性容器实例 ECI (Elastic Container Instance) 是阿里云在云原生时代为用户提供的基础计算 ...
- 图示Java类的初始化顺序
Java类的初始化顺序 在开发中,知道Java类的初始化顺序才能让我们更加清楚地掌握程序的执行流程.先把结论贴出来,Java里,从图里的1~6,分别按顺序执行. 以下为代码验证阶段,一共三个类 ...
- Java基础之 数组详解
前言:Java内功心法之数组详解,看完这篇你向Java大神的路上又迈出了一步(有什么问题或者需要资料可以联系我的扣扣:734999078) 数组概念 同一种类型数据的集合.其实数组就是一个容器. 数组 ...
- Docker镜像构建的两种方式(六)--技术流ken
镜像构建介绍 在什么情况下我们需要自己构建镜像那? (1)当我们找不到现有的镜像,比如自己开发的应用程序 (2)需要在镜像中加入特定的功能 docker构建镜像有两种方式:docker commit命 ...
- VisualStudio移动开发(C#、VB.NET)Smobiler开发平台——VoiceRecorder控件的使用方式.Net移动开发
一. 样式一 我们要实现上图中的效果,需要如下的操作: 从工具栏上的“Smobiler Components”拖动一个VoiceRecorder控件和一个ImageButton控件到 ...
- 第44章 添加新协议 - Identity Server 4 中文文档(v1.0.0)
除了对OpenID Connect和OAuth 2.0的内置支持之外,IdentityServer4还允许添加对其他协议的支持. 您可以将这些附加协议端点添加为中间件或使用例如MVC控制器.在这两种情 ...
- Linux CentOS开机启动项设置命令:chkconfig
1.开机启动+++crontab 定时执行(定时执行可参考:https://www.cnblogs.com/prefectjava/p/9399552.html)可实现自动化运行的目的,简化了维护人员 ...
- 【开源】Netty轻松实现聊天室,附带数据记录,聊天历史
阅读本文约“2.5分钟” 听说快七夕······ 不对,这不是今天的主题,嘿嘿. 今天说说一个小的网页聊天室,功能如下 群聊无限制 记录用户群聊信息 下次登录显示聊天历史 消息发送速度(光速) 聊天历 ...