• C# 指针使用总结


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

    一、Vs2010中开启unsafe code 的方式

    在方法、类、代码块中使用unsafe关键词,如:

    1 unsafe static void Main(string[] args){ //代码}
    2 
    3 unsafe
    4 {
    5 //代码块
    6 }

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

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

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

    三、C#指针操作符

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

    例如分配内存

    1 char* cptr = stackalloc char[26];
    2 for (int i = 0; i < 26;i++ )
    3 {
    4     cptr[i] = (char) (i+65);
    5 }
    6 for (int i = 0; i < 26;i++ )
    7 {
    8     Console.WriteLine(string.Format("{0}:{1}",(int)&cptr[i],cptr[i]));
    9 }

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

    四、C#指针的定义

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

    五、指针的使用

    1.整形指针的使用

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

    2.结构体指针

     1 struct Location
     2 {
     3     public int X;
     4     public int Y;
     5 }
     6 unsafe static void Main(string[] args)
     7 {
     8     Location location;
     9     location.X = 10;
    10     location.Y = 5;
    11     Location* lptr = &location;
    12     Console.WriteLine(string.Format("location 地址{0},lptr地址{1},lptr值{2}",(int)&location,(int)lptr,*lptr));
    13     Console.WriteLine(string.Format("location.x的地址{0},location.x的值{1}",(int)&(lptr->X),lptr->X));
    14     Console.WriteLine(string.Format("location.y的地址{0},location.y的值{1}", (int)&(lptr->Y), lptr->Y));
    15  }

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

    3.指针与参数

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

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

     1 class People
     2 {
     3     public int Age;   //值类型,不可以是属性
     4     public void ShowAge()
     5     {
     6         Console.WriteLine(Age);
     7     }
     8 }
     9 
    10 
    11 People people = new People();
    12 people.Age = 10;
    13 fixed(int* agePtr=&people.Age)
    14 {
    15     *agePtr += 1;
    16 }
    17 people.ShowAge();  //11

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

    1 object p = new People();
    2 GCHandle h = GCHandle.Alloc(p, GCHandleType.Pinned);
    3 IntPtr addr = h.AddrOfPinnedObject(); 
    4 Console.WriteLine(addr.ToString());
    5 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.可以使我们了解非托管类型的内存分配。

  • 相关阅读:
    vs2022 搭建NET6 WebApi 接口项目《五》 接口访问限流配置
    vs2022 搭建NET6 WebApi 接口项目《二》 配置swagger
    vs2022 搭建NET6 WebApi 接口项目《一》 整体项目搭建
    vs2022 搭建NET6 WebApi 接口项目《六》 返回参数配置
    vs2022 搭建NET6 WebApi 接口项目《三》 配置跨域
    Docker 在mac上的使用
    构建煤矿物联网大数据平台思路(1)
    构建煤矿物联网大数据平台思路(2)实时数据库与时序数据库
    Redis 只能通过127.0.0.1访问,磁盘在使用中等问题...
    git 提交忽略bin obj等文件
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/12484404.html
Copyright © 2020-2023  润新知